<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>https://wiki.riguz.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Riguz</id>
	<title>WHY42 - 用户贡献 [zh-cn]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.riguz.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Riguz"/>
	<link rel="alternate" type="text/html" href="https://wiki.riguz.com/%E7%89%B9%E6%AE%8A:%E7%94%A8%E6%88%B7%E8%B4%A1%E7%8C%AE/Riguz"/>
	<updated>2026-06-02T18:43:48Z</updated>
	<subtitle>用户贡献</subtitle>
	<generator>MediaWiki 1.42.3</generator>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Mac_colima&amp;diff=5165</id>
		<title>Mac colima</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Mac_colima&amp;diff=5165"/>
		<updated>2026-05-07T03:52:40Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​创建页面，内容为“  &amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt; sudo ports install docker mkdir -p ~/.docker/cli-plugins curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-darwin-$(uname -m | sed &amp;#039;s/x86_64/x86_64/;s/arm64/aarch64/&amp;#039;) \   -o ~/.docker/cli-plugins/docker-compose chmod +x ~/.docker/cli-plugins/docker-compose docker compose version  colima start &amp;lt;/syntaxhighlight&amp;gt;  Catgory:Linux/Unix”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ports install docker&lt;br /&gt;
mkdir -p ~/.docker/cli-plugins&lt;br /&gt;
curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-darwin-$(uname -m | sed &#039;s/x86_64/x86_64/;s/arm64/aarch64/&#039;) \&lt;br /&gt;
  -o ~/.docker/cli-plugins/docker-compose&lt;br /&gt;
chmod +x ~/.docker/cli-plugins/docker-compose&lt;br /&gt;
docker compose version&lt;br /&gt;
&lt;br /&gt;
colima start&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Catgory:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5164</id>
		<title>Linux server setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5164"/>
		<updated>2026-03-28T14:03:01Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* ssh config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ubuntu server setup:&lt;br /&gt;
&lt;br /&gt;
=System settings =&lt;br /&gt;
Add admin user:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
adduser sammy&lt;br /&gt;
usermod -aG sudo sammy&lt;br /&gt;
su - sammy&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
== Update system ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt upgrade&lt;br /&gt;
do-release-upgrade&lt;br /&gt;
&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== hostname  ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vim /etc/hostname&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== user ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
adduser ubuntu&lt;br /&gt;
usermod -aG sudo ubuntu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ssh config ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh-copy-id -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&lt;br /&gt;
# vim /etc/ssh/sshd_config&lt;br /&gt;
Port 54194&lt;br /&gt;
PermitRootLogin no&lt;br /&gt;
PasswordAuthentication no&lt;br /&gt;
PubkeyAuthentication yes&lt;br /&gt;
&lt;br /&gt;
service ssh restart&lt;br /&gt;
ssh -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: for Ubuntu 24.04+ with systemd socket&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# To change the port&lt;br /&gt;
sudo vim /lib/systemd/system/ssh.socket&lt;br /&gt;
[Socket]&lt;br /&gt;
ListenStream=0.0.0.0:54194&lt;br /&gt;
ListenStream=[::]:54194&lt;br /&gt;
&lt;br /&gt;
sudo systemctl daemon-reload&lt;br /&gt;
sudo systemctl stop ssh.socket&lt;br /&gt;
sudo systemctl restart ssh&lt;br /&gt;
netstat -anp | grep 54194&lt;br /&gt;
(No info could be read for &amp;quot;-p&amp;quot;: geteuid()=1000 but you should be root.)&lt;br /&gt;
tcp        0      0 0.0.0.0:54194           0.0.0.0:*               LISTEN      -&lt;br /&gt;
tcp6       0      0 :::54194                :::*                    LISTEN      -&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ufw==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw allow 80&lt;br /&gt;
sudo ufw allow 443&lt;br /&gt;
sudo ufw allow 50000&lt;br /&gt;
sudo ufw status numbered&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== V2ray ==&lt;br /&gt;
&lt;br /&gt;
[[V2Ray global proxy]]&lt;br /&gt;
&lt;br /&gt;
= Web server =&lt;br /&gt;
== Ngnix ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo apt install nginx&lt;br /&gt;
$ sudo systemctl status nginx&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Certbot ==&lt;br /&gt;
Install via pip&amp;lt;ref&amp;gt;https://certbot.eff.org/instructions?ws=nginx&amp;amp;os=pip&amp;amp;commit=%3E&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt install certbot&lt;br /&gt;
sudo apt install python3 python3-dev python3-venv libaugeas-dev gcc&lt;br /&gt;
sudo python3 -m venv /opt/certbot/&lt;br /&gt;
sudo /opt/certbot/bin/pip install --upgrade pip&lt;br /&gt;
sudo /opt/certbot/bin/pip install certbot certbot-nginx&lt;br /&gt;
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot&lt;br /&gt;
sudo certbot --nginx&lt;br /&gt;
sudo nginx -s reload&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Leetcode_top75&amp;diff=5163</id>
		<title>Leetcode top75</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Leetcode_top75&amp;diff=5163"/>
		<updated>2026-03-25T01:44:20Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Array/String:&lt;br /&gt;
&lt;br /&gt;
* 1768. Merge Strings Alternately: use StringBuilder&lt;br /&gt;
* 1071. Greatest Common Divisor of Strings: if str1 and str2 can be divided, then &lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
str1 + str2 = str2 + str1&lt;br /&gt;
\gcd(a,b)=\gcd(b,a \bmod b)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
just get the substring of gcd length&lt;br /&gt;
* 1431. Kids With the Greatest Number of Candies: find the max value first&lt;br /&gt;
* 605. Can Place Flowers: check neighbours&lt;br /&gt;
* 345. Reverse Vowels of a String: exchange local array&lt;br /&gt;
* 151. Reverse Words in a String: split and then concat/ reverse array&lt;br /&gt;
* 238. Product of Array Except Self: p = p_left * p_right&lt;br /&gt;
* 334. Increasing Triplet Subsequence: tracking the smallest, the second smallest num&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Leetcode_top75&amp;diff=5162</id>
		<title>Leetcode top75</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Leetcode_top75&amp;diff=5162"/>
		<updated>2026-03-25T01:11:20Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Array/String:&lt;br /&gt;
&lt;br /&gt;
* 1768. Merge Strings Alternately: use StringBuilder&lt;br /&gt;
* 1071. Greatest Common Divisor of Strings: if str1 and str2 can be divided, then &lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
str1 + str2 = str2 + str1&lt;br /&gt;
\gcd(a,b)=\gcd(b,a \bmod b)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
just get the substring of gcd length&lt;br /&gt;
* 1431. Kids With the Greatest Number of Candies: find the max value first&lt;br /&gt;
* 605. Can Place Flowers: check neighbours&lt;br /&gt;
* 345. Reverse Vowels of a String: exchange local array&lt;br /&gt;
* 151. Reverse Words in a String: split and then concat/ reverse array&lt;br /&gt;
* 238. Product of Array Except Self: p = p_left * p_right&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Leetcode_top75&amp;diff=5161</id>
		<title>Leetcode top75</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Leetcode_top75&amp;diff=5161"/>
		<updated>2026-03-24T16:23:01Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Array/String:&lt;br /&gt;
&lt;br /&gt;
* 1768. Merge Strings Alternately: use StringBuilder&lt;br /&gt;
* 1071. Greatest Common Divisor of Strings: if str1 and str2 can be divided, then &lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
str1 + str2 = str2 + str1&lt;br /&gt;
\gcd(a,b)=\gcd(b,a \bmod b)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
just get the substring of gcd length&lt;br /&gt;
* 1431. Kids With the Greatest Number of Candies: find the max value first&lt;br /&gt;
* 605. Can Place Flowers: check neighbours&lt;br /&gt;
* 345. Reverse Vowels of a String: exchange local array&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Leetcode_top75&amp;diff=5160</id>
		<title>Leetcode top75</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Leetcode_top75&amp;diff=5160"/>
		<updated>2026-03-24T15:13:57Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Array/String:&lt;br /&gt;
&lt;br /&gt;
* 1768. Merge Strings Alternately: use StringBuilder&lt;br /&gt;
* 1071. Greatest Common Divisor of Strings: if str1 and str2 can be divided, then &lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
str1 + str2 = str2 + str1&lt;br /&gt;
\gcd(a,b)=\gcd(b,a \bmod b)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
just get the substring of gcd length&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Leetcode_top75&amp;diff=5159</id>
		<title>Leetcode top75</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Leetcode_top75&amp;diff=5159"/>
		<updated>2026-03-24T15:13:27Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​创建页面，内容为“Array/String:  * 1768. Merge Strings Alternately: use StringBuilder * 1071. Greatest Common Divisor of Strings: if str1 and str2 can be divided, then  &amp;lt;math&amp;gt; str1 + str2 = str2 + str1 \gcd(a,b)=\gcd(b,a \bmod b) &amp;lt;/math&amp;gt; just get the substring of gcd length”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Array/String:&lt;br /&gt;
&lt;br /&gt;
* 1768. Merge Strings Alternately: use StringBuilder&lt;br /&gt;
* 1071. Greatest Common Divisor of Strings:&lt;br /&gt;
if str1 and str2 can be divided, then &lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
str1 + str2 = str2 + str1&lt;br /&gt;
\gcd(a,b)=\gcd(b,a \bmod b)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
just get the substring of gcd length&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5158</id>
		<title>Linux server setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5158"/>
		<updated>2026-03-06T04:59:51Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* System settings */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ubuntu server setup:&lt;br /&gt;
&lt;br /&gt;
=System settings =&lt;br /&gt;
Add admin user:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
adduser sammy&lt;br /&gt;
usermod -aG sudo sammy&lt;br /&gt;
su - sammy&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
== Update system ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt upgrade&lt;br /&gt;
do-release-upgrade&lt;br /&gt;
&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== hostname  ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vim /etc/hostname&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== user ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
adduser ubuntu&lt;br /&gt;
usermod -aG sudo ubuntu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ssh config ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh-copy-id -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&lt;br /&gt;
# vim /etc/ssh/sshd_config&lt;br /&gt;
PermitRootLogin no&lt;br /&gt;
PasswordAuthentication no&lt;br /&gt;
PubkeyAuthentication yes&lt;br /&gt;
&lt;br /&gt;
service ssh restart&lt;br /&gt;
ssh -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ufw==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw allow 80&lt;br /&gt;
sudo ufw allow 443&lt;br /&gt;
sudo ufw allow 50000&lt;br /&gt;
sudo ufw status numbered&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== V2ray ==&lt;br /&gt;
&lt;br /&gt;
[[V2Ray global proxy]]&lt;br /&gt;
&lt;br /&gt;
= Web server =&lt;br /&gt;
== Ngnix ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo apt install nginx&lt;br /&gt;
$ sudo systemctl status nginx&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Certbot ==&lt;br /&gt;
Install via pip&amp;lt;ref&amp;gt;https://certbot.eff.org/instructions?ws=nginx&amp;amp;os=pip&amp;amp;commit=%3E&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt install certbot&lt;br /&gt;
sudo apt install python3 python3-dev python3-venv libaugeas-dev gcc&lt;br /&gt;
sudo python3 -m venv /opt/certbot/&lt;br /&gt;
sudo /opt/certbot/bin/pip install --upgrade pip&lt;br /&gt;
sudo /opt/certbot/bin/pip install certbot certbot-nginx&lt;br /&gt;
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot&lt;br /&gt;
sudo certbot --nginx&lt;br /&gt;
sudo nginx -s reload&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5157</id>
		<title>Linux server setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5157"/>
		<updated>2026-03-06T04:58:29Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ubuntu server setup:&lt;br /&gt;
&lt;br /&gt;
=System settings =&lt;br /&gt;
== Update system ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt upgrade&lt;br /&gt;
do-release-upgrade&lt;br /&gt;
&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== hostname  ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vim /etc/hostname&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== user ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
adduser ubuntu&lt;br /&gt;
usermod -aG sudo ubuntu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ssh config ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh-copy-id -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&lt;br /&gt;
# vim /etc/ssh/sshd_config&lt;br /&gt;
PermitRootLogin no&lt;br /&gt;
PasswordAuthentication no&lt;br /&gt;
PubkeyAuthentication yes&lt;br /&gt;
&lt;br /&gt;
service ssh restart&lt;br /&gt;
ssh -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ufw==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw allow 80&lt;br /&gt;
sudo ufw allow 443&lt;br /&gt;
sudo ufw allow 50000&lt;br /&gt;
sudo ufw status numbered&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== V2ray ==&lt;br /&gt;
&lt;br /&gt;
[[V2Ray global proxy]]&lt;br /&gt;
&lt;br /&gt;
= Web server =&lt;br /&gt;
== Ngnix ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo apt install nginx&lt;br /&gt;
$ sudo systemctl status nginx&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Certbot ==&lt;br /&gt;
Install via pip&amp;lt;ref&amp;gt;https://certbot.eff.org/instructions?ws=nginx&amp;amp;os=pip&amp;amp;commit=%3E&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt install certbot&lt;br /&gt;
sudo apt install python3 python3-dev python3-venv libaugeas-dev gcc&lt;br /&gt;
sudo python3 -m venv /opt/certbot/&lt;br /&gt;
sudo /opt/certbot/bin/pip install --upgrade pip&lt;br /&gt;
sudo /opt/certbot/bin/pip install certbot certbot-nginx&lt;br /&gt;
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot&lt;br /&gt;
sudo certbot --nginx&lt;br /&gt;
sudo nginx -s reload&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5156</id>
		<title>Rock5b+</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5156"/>
		<updated>2025-12-10T15:34:24Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Armbian */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Install system =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ref&amp;gt;https://docs.radxa.com/rock5/rock5b/getting-started/install-os/boot_from_sd_card&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Prerequsits:&lt;br /&gt;
&lt;br /&gt;
* Install Etcher&lt;br /&gt;
&lt;br /&gt;
== Rock5b+ Official image ==&lt;br /&gt;
Download image from rock site https://docs.radxa.com/rock5/rock5b/download:&lt;br /&gt;
&lt;br /&gt;
rock-5b-plus_bookworm_kde_b2.output.img.xz&lt;br /&gt;
&lt;br /&gt;
Note that the image must be decompressed first.&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-rock5b.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-rock5b-finished.png|600px]]&lt;br /&gt;
&lt;br /&gt;
You may get error like:&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-error-mac.png|600px]]&lt;br /&gt;
&lt;br /&gt;
Grant full disk access to etcher in privacy setting and run as sudo user:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
# see https://github.com/balena-io/etcher/issues/4451&lt;br /&gt;
sudo open -a balenaEtcher&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Armbian ==&lt;br /&gt;
&lt;br /&gt;
Download image from https://www.armbian.com/rock-5b-plus/.&lt;br /&gt;
&lt;br /&gt;
eg.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot; inline&amp;gt;Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the xz file must be extracted before writing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
shasum -a 256  ~/Downloads/Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&lt;br /&gt;
d3977e1bb9932b35a10e891fddb4e5d4840d709f2094c5a0cfdfb15cfa97b522  /Users/riguz/Downloads/Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Write to image using etcher or USBImager. &amp;lt;ref&amp;gt;https://docs.armbian.com/User-Guide_Getting-Started/&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(base) ➜  ~ picocom -b 1500000 -d 8 /dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
picocom v3.2a&lt;br /&gt;
&lt;br /&gt;
port is        : /dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
flowcontrol    : none&lt;br /&gt;
baudrate is    : 1500000&lt;br /&gt;
parity is      : none&lt;br /&gt;
databits are   : 8&lt;br /&gt;
stopbits are   : 1&lt;br /&gt;
escape is      : C-a&lt;br /&gt;
local echo is  : no&lt;br /&gt;
noinit is      : no&lt;br /&gt;
noreset is     : no&lt;br /&gt;
hangup is      : no&lt;br /&gt;
nolock is      : no&lt;br /&gt;
send_cmd is    : sz -vv&lt;br /&gt;
receive_cmd is : rz -vv -E&lt;br /&gt;
imap is        :&lt;br /&gt;
omap is        :&lt;br /&gt;
emap is        : crcrlf,delbs,&lt;br /&gt;
logfile is     : none&lt;br /&gt;
initstring     : none&lt;br /&gt;
exit_after is  : not set&lt;br /&gt;
exit is        : no&lt;br /&gt;
&lt;br /&gt;
Type [C-a] [C-h] to see available commands&lt;br /&gt;
Terminal ready&lt;br /&gt;
&lt;br /&gt;
Repeat root password: ****&lt;br /&gt;
Rejected - passwords do not match. Try again [3].&lt;br /&gt;
Create root password: *********&lt;br /&gt;
Repeat root password: *********&lt;br /&gt;
&lt;br /&gt;
Choose default system command shell:&lt;br /&gt;
&lt;br /&gt;
1) bash&lt;br /&gt;
2) zsh&lt;br /&gt;
2&lt;br /&gt;
&lt;br /&gt;
Shell: ZSH&lt;br /&gt;
&lt;br /&gt;
Creating a new user account. Press &amp;lt;Ctrl-C&amp;gt; to abort&lt;br /&gt;
&lt;br /&gt;
Desktop environment will not be enabled if you abort the new user creation&lt;br /&gt;
&lt;br /&gt;
Please provide a username (eg. your first name): riguz&lt;br /&gt;
Create user (riguz) password: *********&lt;br /&gt;
Repeat user (riguz) password: *********&lt;br /&gt;
&lt;br /&gt;
Please provide your real name: Riguz&lt;br /&gt;
&lt;br /&gt;
Dear Riguz, your account riguz has been created and is sudo enabled.&lt;br /&gt;
Please use this account for your daily work from now on.&lt;br /&gt;
&lt;br /&gt;
Internet connection was not detected.&lt;br /&gt;
&lt;br /&gt;
Connect via wireless? [Y/n]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TTL connection ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ls /dev/tty.*&lt;br /&gt;
/dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
picocom -b 1500000 -d 8 /dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Install system ==&lt;br /&gt;
&lt;br /&gt;
[[Category:Embedding]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5155</id>
		<title>Rock5b+</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5155"/>
		<updated>2025-12-10T15:24:37Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Armbian */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Install system =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ref&amp;gt;https://docs.radxa.com/rock5/rock5b/getting-started/install-os/boot_from_sd_card&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Prerequsits:&lt;br /&gt;
&lt;br /&gt;
* Install Etcher&lt;br /&gt;
&lt;br /&gt;
== Rock5b+ Official image ==&lt;br /&gt;
Download image from rock site https://docs.radxa.com/rock5/rock5b/download:&lt;br /&gt;
&lt;br /&gt;
rock-5b-plus_bookworm_kde_b2.output.img.xz&lt;br /&gt;
&lt;br /&gt;
Note that the image must be decompressed first.&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-rock5b.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-rock5b-finished.png|600px]]&lt;br /&gt;
&lt;br /&gt;
You may get error like:&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-error-mac.png|600px]]&lt;br /&gt;
&lt;br /&gt;
Grant full disk access to etcher in privacy setting and run as sudo user:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
# see https://github.com/balena-io/etcher/issues/4451&lt;br /&gt;
sudo open -a balenaEtcher&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Armbian ==&lt;br /&gt;
&lt;br /&gt;
Download image from https://www.armbian.com/rock-5b-plus/.&lt;br /&gt;
&lt;br /&gt;
eg.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot; inline&amp;gt;Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the xz file must be extracted before writing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
shasum -a 256  ~/Downloads/Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&lt;br /&gt;
d3977e1bb9932b35a10e891fddb4e5d4840d709f2094c5a0cfdfb15cfa97b522  /Users/riguz/Downloads/Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Write to image using etcher or USBImager. &amp;lt;ref&amp;gt;https://docs.armbian.com/User-Guide_Getting-Started/&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TTL connection ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ls /dev/tty.*&lt;br /&gt;
/dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
picocom -b 1500000 -d 8 /dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Install system ==&lt;br /&gt;
&lt;br /&gt;
[[Category:Embedding]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5154</id>
		<title>Rock5b+</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5154"/>
		<updated>2025-12-10T14:57:46Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Rock5b+ Official image */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Install system =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ref&amp;gt;https://docs.radxa.com/rock5/rock5b/getting-started/install-os/boot_from_sd_card&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Prerequsits:&lt;br /&gt;
&lt;br /&gt;
* Install Etcher&lt;br /&gt;
&lt;br /&gt;
== Rock5b+ Official image ==&lt;br /&gt;
Download image from rock site https://docs.radxa.com/rock5/rock5b/download:&lt;br /&gt;
&lt;br /&gt;
rock-5b-plus_bookworm_kde_b2.output.img.xz&lt;br /&gt;
&lt;br /&gt;
Note that the image must be decompressed first.&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-rock5b.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-rock5b-finished.png|600px]]&lt;br /&gt;
&lt;br /&gt;
You may get error like:&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-error-mac.png|600px]]&lt;br /&gt;
&lt;br /&gt;
Grant full disk access to etcher in privacy setting and run as sudo user:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
# see https://github.com/balena-io/etcher/issues/4451&lt;br /&gt;
sudo open -a balenaEtcher&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Armbian ==&lt;br /&gt;
&lt;br /&gt;
Download image from https://www.armbian.com/rock-5b-plus/.&lt;br /&gt;
&lt;br /&gt;
eg.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot; inline&amp;gt;Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the xz file must be extracted before writing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
shasum -a 256  ~/Downloads/Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&lt;br /&gt;
d3977e1bb9932b35a10e891fddb4e5d4840d709f2094c5a0cfdfb15cfa97b522  /Users/riguz/Downloads/Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TTL connection ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ls /dev/tty.*&lt;br /&gt;
/dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
picocom -b 1500000 -d 8 /dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Install system ==&lt;br /&gt;
&lt;br /&gt;
[[Category:Embedding]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=%E6%96%87%E4%BB%B6:Etcher-error-mac.png&amp;diff=5153</id>
		<title>文件:Etcher-error-mac.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=%E6%96%87%E4%BB%B6:Etcher-error-mac.png&amp;diff=5153"/>
		<updated>2025-12-10T14:56:47Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5152</id>
		<title>Rock5b+</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5152"/>
		<updated>2025-12-10T14:56:19Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Rock5b+ Official image */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Install system =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ref&amp;gt;https://docs.radxa.com/rock5/rock5b/getting-started/install-os/boot_from_sd_card&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Prerequsits:&lt;br /&gt;
&lt;br /&gt;
* Install Etcher&lt;br /&gt;
&lt;br /&gt;
== Rock5b+ Official image ==&lt;br /&gt;
Download image from rock site https://docs.radxa.com/rock5/rock5b/download:&lt;br /&gt;
&lt;br /&gt;
rock-5b-plus_bookworm_kde_b2.output.img.xz&lt;br /&gt;
&lt;br /&gt;
Note that the image must be decompressed first.&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-rock5b.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-rock5b-finished.png|600px]]&lt;br /&gt;
&lt;br /&gt;
You may get error like:&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-error-mac.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
# see https://github.com/balena-io/etcher/issues/4451&lt;br /&gt;
sudo open -a balenaEtcher&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Armbian ==&lt;br /&gt;
&lt;br /&gt;
Download image from https://www.armbian.com/rock-5b-plus/.&lt;br /&gt;
&lt;br /&gt;
eg.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot; inline&amp;gt;Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the xz file must be extracted before writing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
shasum -a 256  ~/Downloads/Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&lt;br /&gt;
d3977e1bb9932b35a10e891fddb4e5d4840d709f2094c5a0cfdfb15cfa97b522  /Users/riguz/Downloads/Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TTL connection ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ls /dev/tty.*&lt;br /&gt;
/dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
picocom -b 1500000 -d 8 /dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Install system ==&lt;br /&gt;
&lt;br /&gt;
[[Category:Embedding]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5151</id>
		<title>Rock5b+</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5151"/>
		<updated>2025-12-10T14:55:07Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Armbian */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Install system =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ref&amp;gt;https://docs.radxa.com/rock5/rock5b/getting-started/install-os/boot_from_sd_card&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Prerequsits:&lt;br /&gt;
&lt;br /&gt;
* Install Etcher&lt;br /&gt;
&lt;br /&gt;
== Rock5b+ Official image ==&lt;br /&gt;
Download image from rock site https://docs.radxa.com/rock5/rock5b/download:&lt;br /&gt;
&lt;br /&gt;
rock-5b-plus_bookworm_kde_b2.output.img.xz&lt;br /&gt;
&lt;br /&gt;
Note that the image must be decompressed first.&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-rock5b.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-rock5b-finished.png|600px]]&lt;br /&gt;
&lt;br /&gt;
== Armbian ==&lt;br /&gt;
&lt;br /&gt;
Download image from https://www.armbian.com/rock-5b-plus/.&lt;br /&gt;
&lt;br /&gt;
eg.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot; inline&amp;gt;Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the xz file must be extracted before writing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
shasum -a 256  ~/Downloads/Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&lt;br /&gt;
d3977e1bb9932b35a10e891fddb4e5d4840d709f2094c5a0cfdfb15cfa97b522  /Users/riguz/Downloads/Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TTL connection ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ls /dev/tty.*&lt;br /&gt;
/dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
picocom -b 1500000 -d 8 /dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Install system ==&lt;br /&gt;
&lt;br /&gt;
[[Category:Embedding]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5150</id>
		<title>Rock5b+</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5150"/>
		<updated>2025-12-10T14:30:09Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Rock5b+ Official image */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Install system =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ref&amp;gt;https://docs.radxa.com/rock5/rock5b/getting-started/install-os/boot_from_sd_card&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Prerequsits:&lt;br /&gt;
&lt;br /&gt;
* Install Etcher&lt;br /&gt;
&lt;br /&gt;
== Rock5b+ Official image ==&lt;br /&gt;
Download image from rock site https://docs.radxa.com/rock5/rock5b/download:&lt;br /&gt;
&lt;br /&gt;
rock-5b-plus_bookworm_kde_b2.output.img.xz&lt;br /&gt;
&lt;br /&gt;
Note that the image must be decompressed first.&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-rock5b.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-rock5b-finished.png|600px]]&lt;br /&gt;
&lt;br /&gt;
== Armbian ==&lt;br /&gt;
&lt;br /&gt;
Download image from https://www.armbian.com/rock-5b-plus/.&lt;br /&gt;
&lt;br /&gt;
eg.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot; inline&amp;gt;Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the xz file must be extracted before writing.&lt;br /&gt;
&lt;br /&gt;
== TTL connection ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ls /dev/tty.*&lt;br /&gt;
/dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
picocom -b 1500000 -d 8 /dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Install system ==&lt;br /&gt;
&lt;br /&gt;
[[Category:Embedding]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=%E6%96%87%E4%BB%B6:Etcher-rock5b-finished.png&amp;diff=5149</id>
		<title>文件:Etcher-rock5b-finished.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=%E6%96%87%E4%BB%B6:Etcher-rock5b-finished.png&amp;diff=5149"/>
		<updated>2025-12-10T14:29:35Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=%E6%96%87%E4%BB%B6:Etcher-rock5b.png&amp;diff=5148</id>
		<title>文件:Etcher-rock5b.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=%E6%96%87%E4%BB%B6:Etcher-rock5b.png&amp;diff=5148"/>
		<updated>2025-12-10T14:28:52Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5147</id>
		<title>Rock5b+</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5147"/>
		<updated>2025-12-10T14:28:22Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Install system */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Install system =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ref&amp;gt;https://docs.radxa.com/rock5/rock5b/getting-started/install-os/boot_from_sd_card&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Prerequsits:&lt;br /&gt;
&lt;br /&gt;
* Install Etcher&lt;br /&gt;
&lt;br /&gt;
== Rock5b+ Official image ==&lt;br /&gt;
Download image from rock site https://docs.radxa.com/rock5/rock5b/download:&lt;br /&gt;
&lt;br /&gt;
rock-5b-plus_bookworm_kde_b2.output.img.xz&lt;br /&gt;
&lt;br /&gt;
Note that the image must be decompressed first.&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-rock5b.png|600px]]&lt;br /&gt;
&lt;br /&gt;
[[Image:etcher-rock5b-finished.png|600px]]&lt;br /&gt;
&lt;br /&gt;
== Armbian ==&lt;br /&gt;
&lt;br /&gt;
Download image from https://www.armbian.com/rock-5b-plus/.&lt;br /&gt;
&lt;br /&gt;
eg.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot; inline&amp;gt;Armbian_25.11.1_Rock-5b_noble_vendor_6.1.115_gnome_desktop.img.xz&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the xz file must be extracted before writing.&lt;br /&gt;
&lt;br /&gt;
== TTL connection ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ls /dev/tty.*&lt;br /&gt;
/dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
picocom -b 1500000 -d 8 /dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Install system ==&lt;br /&gt;
&lt;br /&gt;
[[Category:Embedding]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5146</id>
		<title>Rock5b+</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Rock5b%2B&amp;diff=5146"/>
		<updated>2025-11-04T14:01:48Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​创建页面，内容为“= Install system = == TTL connection ==  &amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt; ls /dev/tty.* /dev/tty.wchusbserial5ABA0915851 picocom -b 1500000 -d 8 /dev/tty.wchusbserial5ABA0915851 &amp;lt;/syntaxhighlight&amp;gt;  == Install system ==  Category:Embedding”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Install system =&lt;br /&gt;
== TTL connection ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ls /dev/tty.*&lt;br /&gt;
/dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
picocom -b 1500000 -d 8 /dev/tty.wchusbserial5ABA0915851&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Install system ==&lt;br /&gt;
&lt;br /&gt;
[[Category:Embedding]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Keycloak&amp;diff=5145</id>
		<title>Keycloak</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Keycloak&amp;diff=5145"/>
		<updated>2025-10-08T09:54:02Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Install ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker network create dev-zone&lt;br /&gt;
docker stop yai-postgres &amp;amp;&amp;amp; docker rm yai-postgres&lt;br /&gt;
docker run \&lt;br /&gt;
    --name yai-postgres \&lt;br /&gt;
    -p 5432:5432 \&lt;br /&gt;
    -e POSTGRES_USER=${POSTGRES_USER} \&lt;br /&gt;
    -e POSTGRES_DB=development-db \&lt;br /&gt;
    -e POSTGRES_PASSWORD=${POSTGRES_PASSWORD} \&lt;br /&gt;
    -v ./postgres-data:/var/lib/postgresql/18/docker \&lt;br /&gt;
    --network dev-zone \&lt;br /&gt;
    -d postgres:18&lt;br /&gt;
&lt;br /&gt;
# create the schema manually&lt;br /&gt;
&lt;br /&gt;
docker run --name yai-keycloak \&lt;br /&gt;
  -p 8081:8080 -d \&lt;br /&gt;
  -e KC_BOOTSTRAP_ADMIN_USERNAME=${KC_BOOTSTRAP_ADMIN_USERNAME} \&lt;br /&gt;
  -e KC_BOOTSTRAP_ADMIN_PASSWORD=${KC_BOOTSTRAP_ADMIN_PASSWORD} \&lt;br /&gt;
  -e KC_DB=postgres \&lt;br /&gt;
  -e KC_DB_URL=jdbc:postgresql://yai-postgres:5432/development-db \&lt;br /&gt;
  -e KC_DB_SCHEMA=keycloak \&lt;br /&gt;
  -e KC_DB_USERNAME=${POSTGRES_USER} \&lt;br /&gt;
  -e KC_DB_PASSWORD=${POSTGRES_PASSWORD} \&lt;br /&gt;
  --network yai-zone \&lt;br /&gt;
  quay.io/keycloak/keycloak:26.3.2 start-dev \&lt;br /&gt;
  --hostname=https://auth.example.com&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reversed proxy&amp;lt;ref&amp;gt;https://medium.com/@asynchronouscal/keycloak-production-mode-with-docker-step-by-step-guide-b284927e72c0&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;https://www.keycloak.org/server/reverseproxy&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;config&amp;quot;&amp;gt;&lt;br /&gt;
server {&lt;br /&gt;
&lt;br /&gt;
    server_name oauth.example.com;&lt;br /&gt;
&lt;br /&gt;
    location / {&lt;br /&gt;
        root   html;&lt;br /&gt;
        index  index.html index.htm;&lt;br /&gt;
        proxy_pass  http://localhost:8081;&lt;br /&gt;
&lt;br /&gt;
	       proxy_redirect off;&lt;br /&gt;
           proxy_set_header Host $host;&lt;br /&gt;
           proxy_set_header X-Real-IP $remote_addr;&lt;br /&gt;
           proxy_set_header X-Forwarded-For $remote_addr;&lt;br /&gt;
           proxy_set_header X-Forwarded-Proto $scheme;&lt;br /&gt;
           proxy_set_header X-Forwarded-Port 443;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure ==&lt;br /&gt;
* Create realm: my-org&lt;br /&gt;
* Create users: whatever&lt;br /&gt;
* Create client: my-app&lt;br /&gt;
&lt;br /&gt;
* Client ID: my-app&lt;br /&gt;
* Valid redirect URIs: http://localhost:5173/auth/callback&lt;br /&gt;
* Valid post logout redirect URIs : http://localhost:5173&lt;br /&gt;
* Web origins: http://localhost:5173 (No slash at end!!!)&lt;br /&gt;
* Client authentication: off (for public clients)&lt;br /&gt;
* Authentication flow: Standard flow, Direct access grants&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:OAuth]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Keycloak&amp;diff=5144</id>
		<title>Keycloak</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Keycloak&amp;diff=5144"/>
		<updated>2025-10-06T15:18:47Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Install */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Install ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker network create dev-zone&lt;br /&gt;
docker stop yai-postgres &amp;amp;&amp;amp; docker rm yai-postgres&lt;br /&gt;
docker run \&lt;br /&gt;
    --name yai-postgres \&lt;br /&gt;
    -p 5432:5432 \&lt;br /&gt;
    -e POSTGRES_USER=${POSTGRES_USER} \&lt;br /&gt;
    -e POSTGRES_DB=development-db \&lt;br /&gt;
    -e POSTGRES_PASSWORD=${POSTGRES_PASSWORD} \&lt;br /&gt;
    -v ./postgres-data:/var/lib/postgresql/18/docker \&lt;br /&gt;
    --network dev-zone \&lt;br /&gt;
    -d postgres:18&lt;br /&gt;
&lt;br /&gt;
docker run --name yai-keycloak \&lt;br /&gt;
  -p 8081:8080 -d \&lt;br /&gt;
  -e KC_BOOTSTRAP_ADMIN_USERNAME=${KC_BOOTSTRAP_ADMIN_USERNAME} \&lt;br /&gt;
  -e KC_BOOTSTRAP_ADMIN_PASSWORD=${KC_BOOTSTRAP_ADMIN_PASSWORD} \&lt;br /&gt;
  -e KC_DB=postgres \&lt;br /&gt;
  -e KC_DB_URL=jdbc:postgresql://yai-postgres:5432/development-db \&lt;br /&gt;
  -e KC_DB_SCHEMA=keycloak \&lt;br /&gt;
  -e KC_DB_USERNAME=${POSTGRES_USER} \&lt;br /&gt;
  -e KC_DB_PASSWORD=${POSTGRES_PASSWORD} \&lt;br /&gt;
  --network yai-zone \&lt;br /&gt;
  quay.io/keycloak/keycloak:26.3.2 start-dev \&lt;br /&gt;
  --hostname=https://auth.example.com&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reversed proxy&amp;lt;ref&amp;gt;https://medium.com/@asynchronouscal/keycloak-production-mode-with-docker-step-by-step-guide-b284927e72c0&amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt;https://www.keycloak.org/server/reverseproxy&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;config&amp;quot;&amp;gt;&lt;br /&gt;
server {&lt;br /&gt;
&lt;br /&gt;
    server_name oauth.example.com;&lt;br /&gt;
&lt;br /&gt;
    location / {&lt;br /&gt;
        root   html;&lt;br /&gt;
        index  index.html index.htm;&lt;br /&gt;
        proxy_pass  http://localhost:8081;&lt;br /&gt;
&lt;br /&gt;
	       proxy_redirect off;&lt;br /&gt;
           proxy_set_header Host $host;&lt;br /&gt;
           proxy_set_header X-Real-IP $remote_addr;&lt;br /&gt;
           proxy_set_header X-Forwarded-For $remote_addr;&lt;br /&gt;
           proxy_set_header X-Forwarded-Proto $scheme;&lt;br /&gt;
           proxy_set_header X-Forwarded-Port 443;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure ==&lt;br /&gt;
* Create realm: my-org&lt;br /&gt;
* Create users: whatever&lt;br /&gt;
* Create client: my-app&lt;br /&gt;
&lt;br /&gt;
* Client ID: my-app&lt;br /&gt;
* Valid redirect URIs: http://localhost:5173/auth/callback&lt;br /&gt;
* Valid post logout redirect URIs : http://localhost:5173&lt;br /&gt;
* Web origins: http://localhost:5173 (No slash at end!!!)&lt;br /&gt;
* Client authentication: off (for public clients)&lt;br /&gt;
* Authentication flow: Standard flow, Direct access grants&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:OAuth]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Sphinx&amp;diff=5143</id>
		<title>Sphinx</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Sphinx&amp;diff=5143"/>
		<updated>2025-10-06T10:57:04Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
pip install sphinx myst-parser&lt;br /&gt;
pip install sphinxcontrib-bibtex sphinx-design sphinx-copybutton sphinxext-opengraph&lt;br /&gt;
pip install sphinx-mathjax-offline&lt;br /&gt;
pip install sphinx-book-theme   &lt;br /&gt;
&lt;br /&gt;
cd blog&lt;br /&gt;
sphinx-quickstart&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Sphinx&amp;diff=5142</id>
		<title>Sphinx</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Sphinx&amp;diff=5142"/>
		<updated>2025-10-06T01:45:03Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​创建页面，内容为“&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt; pip install sphinx myst-parser pip install sphinxcontrib-bibtex sphinx-design sphinx-copybutton sphinxext-opengraph pip install sphinx-mathjax-offline   cd blog sphinx-quickstart &amp;lt;/syntaxhighlight&amp;gt;”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
pip install sphinx myst-parser&lt;br /&gt;
pip install sphinxcontrib-bibtex sphinx-design sphinx-copybutton sphinxext-opengraph&lt;br /&gt;
pip install sphinx-mathjax-offline&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
cd blog&lt;br /&gt;
sphinx-quickstart&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5141</id>
		<title>Linux server setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5141"/>
		<updated>2025-10-05T14:44:19Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Web server */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=System settings =&lt;br /&gt;
== Update system ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt upgrade&lt;br /&gt;
do-release-upgrade&lt;br /&gt;
&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== hostname  ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vim /etc/hostname&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== user ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
adduser ubuntu&lt;br /&gt;
usermod -aG sudo ubuntu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ssh config ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh-copy-id -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&lt;br /&gt;
# vim /etc/ssh/sshd_config&lt;br /&gt;
PermitRootLogin no&lt;br /&gt;
PasswordAuthentication no&lt;br /&gt;
PubkeyAuthentication yes&lt;br /&gt;
&lt;br /&gt;
service ssh restart&lt;br /&gt;
ssh -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ufw==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw allow 80&lt;br /&gt;
sudo ufw allow 443&lt;br /&gt;
sudo ufw allow 50000&lt;br /&gt;
sudo ufw status numbered&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== V2ray ==&lt;br /&gt;
&lt;br /&gt;
[[V2Ray global proxy]]&lt;br /&gt;
&lt;br /&gt;
= Web server =&lt;br /&gt;
== Ngnix ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo apt install nginx&lt;br /&gt;
$ sudo systemctl status nginx&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Certbot ==&lt;br /&gt;
Install via pip&amp;lt;ref&amp;gt;https://certbot.eff.org/instructions?ws=nginx&amp;amp;os=pip&amp;amp;commit=%3E&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt install certbot&lt;br /&gt;
sudo apt install python3 python3-dev python3-venv libaugeas-dev gcc&lt;br /&gt;
sudo python3 -m venv /opt/certbot/&lt;br /&gt;
sudo /opt/certbot/bin/pip install --upgrade pip&lt;br /&gt;
sudo /opt/certbot/bin/pip install certbot certbot-nginx&lt;br /&gt;
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot&lt;br /&gt;
sudo certbot --nginx&lt;br /&gt;
sudo nginx -s reload&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5140</id>
		<title>Linux server setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5140"/>
		<updated>2025-10-05T10:38:26Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* V2ray */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=System settings =&lt;br /&gt;
== Update system ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt upgrade&lt;br /&gt;
do-release-upgrade&lt;br /&gt;
&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== hostname  ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vim /etc/hostname&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== user ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
adduser ubuntu&lt;br /&gt;
usermod -aG sudo ubuntu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ssh config ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh-copy-id -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&lt;br /&gt;
# vim /etc/ssh/sshd_config&lt;br /&gt;
PermitRootLogin no&lt;br /&gt;
PasswordAuthentication no&lt;br /&gt;
PubkeyAuthentication yes&lt;br /&gt;
&lt;br /&gt;
service ssh restart&lt;br /&gt;
ssh -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ufw==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw allow 80&lt;br /&gt;
sudo ufw allow 443&lt;br /&gt;
sudo ufw allow 50000&lt;br /&gt;
sudo ufw status numbered&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== V2ray ==&lt;br /&gt;
&lt;br /&gt;
[[V2Ray global proxy]]&lt;br /&gt;
&lt;br /&gt;
= Web server =&lt;br /&gt;
== Ngnix ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo apt install nginx&lt;br /&gt;
$ sudo systemctl status nginx&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5139</id>
		<title>Linux server setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5139"/>
		<updated>2025-10-05T10:00:14Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* V2ray */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=System settings =&lt;br /&gt;
== Update system ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt upgrade&lt;br /&gt;
do-release-upgrade&lt;br /&gt;
&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== hostname  ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vim /etc/hostname&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== user ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
adduser ubuntu&lt;br /&gt;
usermod -aG sudo ubuntu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ssh config ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh-copy-id -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&lt;br /&gt;
# vim /etc/ssh/sshd_config&lt;br /&gt;
PermitRootLogin no&lt;br /&gt;
PasswordAuthentication no&lt;br /&gt;
PubkeyAuthentication yes&lt;br /&gt;
&lt;br /&gt;
service ssh restart&lt;br /&gt;
ssh -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ufw==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw allow 80&lt;br /&gt;
sudo ufw allow 443&lt;br /&gt;
sudo ufw allow 50000&lt;br /&gt;
sudo ufw status numbered&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== V2ray ==&lt;br /&gt;
&lt;br /&gt;
[[V2Ray global proxy]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5138</id>
		<title>Linux server setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5138"/>
		<updated>2025-10-05T10:00:06Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* System settings */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=System settings =&lt;br /&gt;
== Update system ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt upgrade&lt;br /&gt;
do-release-upgrade&lt;br /&gt;
&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== hostname  ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vim /etc/hostname&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== user ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
adduser ubuntu&lt;br /&gt;
usermod -aG sudo ubuntu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ssh config ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh-copy-id -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&lt;br /&gt;
# vim /etc/ssh/sshd_config&lt;br /&gt;
PermitRootLogin no&lt;br /&gt;
PasswordAuthentication no&lt;br /&gt;
PubkeyAuthentication yes&lt;br /&gt;
&lt;br /&gt;
service ssh restart&lt;br /&gt;
ssh -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ufw==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw allow 80&lt;br /&gt;
sudo ufw allow 443&lt;br /&gt;
sudo ufw allow 50000&lt;br /&gt;
sudo ufw status numbered&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== V2ray ==&lt;br /&gt;
&lt;br /&gt;
[V2Ray global proxy]&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=V2Ray_global_proxy&amp;diff=5137</id>
		<title>V2Ray global proxy</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=V2Ray_global_proxy&amp;diff=5137"/>
		<updated>2025-10-05T09:59:22Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Basic Config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Install V2Ray (Server side) =&lt;br /&gt;
== Install ==&lt;br /&gt;
https://github.com/v2fly/fhs-install-v2ray&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# switch to root user and then install&lt;br /&gt;
$ sudo su -&lt;br /&gt;
&lt;br /&gt;
$ bash &amp;lt;(curl -L https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh)&lt;br /&gt;
$ systemctl enable v2ray&lt;br /&gt;
$ systemctl start v2ray&lt;br /&gt;
&lt;br /&gt;
$ bash &amp;lt;(curl -L https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-dat-release.sh)&lt;br /&gt;
&lt;br /&gt;
$ v2ray version&lt;br /&gt;
V2Ray 5.22.0 (V2Fly, a community-driven edition of V2Ray.) Custom (go1.23.2 linux/amd64)&lt;br /&gt;
A unified platform for anti-censorship.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Basic Config ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ systemctl status v2ray&lt;br /&gt;
● v2ray.service - V2Ray Service&lt;br /&gt;
     Loaded: loaded (/etc/systemd/system/v2ray.service; enabled; preset: enable&amp;gt;&lt;br /&gt;
    Drop-In: /etc/systemd/system/v2ray.service.d&lt;br /&gt;
             └─10-donot_touch_single_conf.conf&lt;br /&gt;
     Active: active (running) since Fri 2025-04-18 14:11:22 UTC; 5 months 17 da&amp;gt;&lt;br /&gt;
       Docs: https://www.v2fly.org/&lt;br /&gt;
   Main PID: 719 (v2ray)&lt;br /&gt;
      Tasks: 14 (limit: 9441)&lt;br /&gt;
     Memory: 35.8M (peak: 103.4M)&lt;br /&gt;
        CPU: 8h 56min 41.528s&lt;br /&gt;
     CGroup: /system.slice/v2ray.service&lt;br /&gt;
             └─719 /usr/local/bin/v2ray run -config /usr/local/etc/v2ray/config&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: some journal files were not opened due to insufficient permissions.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/usr/local/etc/v2ray/config.json&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;inbounds&amp;quot;: [{&lt;br /&gt;
    &amp;quot;port&amp;quot;: 10086,&lt;br /&gt;
    &amp;quot;protocol&amp;quot;: &amp;quot;vmess&amp;quot;,&lt;br /&gt;
    &amp;quot;settings&amp;quot;: {&lt;br /&gt;
      &amp;quot;clients&amp;quot;: [{ &amp;quot;id&amp;quot;: &amp;quot;b831381d-6324-4d53-ad4f-8cda48b30811&amp;quot; }]&lt;br /&gt;
    }&lt;br /&gt;
  }],&lt;br /&gt;
  &amp;quot;outbounds&amp;quot;: [{&lt;br /&gt;
    &amp;quot;protocol&amp;quot;: &amp;quot;freedom&amp;quot;,&lt;br /&gt;
    &amp;quot;settings&amp;quot;: {}&lt;br /&gt;
  }]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
restart v2ray server:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo systemctl restart v2ray&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== V2RayU Client ==&lt;br /&gt;
Configure -&amp;gt; add v2ray server, input ip/port and client id.&lt;br /&gt;
&lt;br /&gt;
Git ssh over socks proxy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# vim ~/.ssh/config&lt;br /&gt;
Host github.com&lt;br /&gt;
HostName github.com&lt;br /&gt;
User git&lt;br /&gt;
ProxyCommand nc -v -x 127.0.0.1:1080 %h %p&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=V2Ray_global_proxy&amp;diff=5136</id>
		<title>V2Ray global proxy</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=V2Ray_global_proxy&amp;diff=5136"/>
		<updated>2025-10-05T09:43:01Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Install */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Install V2Ray (Server side) =&lt;br /&gt;
== Install ==&lt;br /&gt;
https://github.com/v2fly/fhs-install-v2ray&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# switch to root user and then install&lt;br /&gt;
$ sudo su -&lt;br /&gt;
&lt;br /&gt;
$ bash &amp;lt;(curl -L https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh)&lt;br /&gt;
$ systemctl enable v2ray&lt;br /&gt;
$ systemctl start v2ray&lt;br /&gt;
&lt;br /&gt;
$ bash &amp;lt;(curl -L https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-dat-release.sh)&lt;br /&gt;
&lt;br /&gt;
$ v2ray version&lt;br /&gt;
V2Ray 5.22.0 (V2Fly, a community-driven edition of V2Ray.) Custom (go1.23.2 linux/amd64)&lt;br /&gt;
A unified platform for anti-censorship.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Basic Config ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ systemctl status v2ray&lt;br /&gt;
● v2ray.service - V2Ray Service&lt;br /&gt;
     Loaded: loaded (/etc/systemd/system/v2ray.service; enabled; preset: enable&amp;gt;&lt;br /&gt;
    Drop-In: /etc/systemd/system/v2ray.service.d&lt;br /&gt;
             └─10-donot_touch_single_conf.conf&lt;br /&gt;
     Active: active (running) since Fri 2025-04-18 14:11:22 UTC; 5 months 17 da&amp;gt;&lt;br /&gt;
       Docs: https://www.v2fly.org/&lt;br /&gt;
   Main PID: 719 (v2ray)&lt;br /&gt;
      Tasks: 14 (limit: 9441)&lt;br /&gt;
     Memory: 35.8M (peak: 103.4M)&lt;br /&gt;
        CPU: 8h 56min 41.528s&lt;br /&gt;
     CGroup: /system.slice/v2ray.service&lt;br /&gt;
             └─719 /usr/local/bin/v2ray run -config /usr/local/etc/v2ray/config&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: some journal files were not opened due to insufficient permissions.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/usr/local/etc/v2ray/config.json&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;inbounds&amp;quot;: [{&lt;br /&gt;
    &amp;quot;port&amp;quot;: 10086,&lt;br /&gt;
    &amp;quot;protocol&amp;quot;: &amp;quot;vmess&amp;quot;,&lt;br /&gt;
    &amp;quot;settings&amp;quot;: {&lt;br /&gt;
      &amp;quot;clients&amp;quot;: [{ &amp;quot;id&amp;quot;: &amp;quot;b831381d-6324-4d53-ad4f-8cda48b30811&amp;quot; }]&lt;br /&gt;
    }&lt;br /&gt;
  }],&lt;br /&gt;
  &amp;quot;outbounds&amp;quot;: [{&lt;br /&gt;
    &amp;quot;protocol&amp;quot;: &amp;quot;freedom&amp;quot;,&lt;br /&gt;
    &amp;quot;settings&amp;quot;: {}&lt;br /&gt;
  }]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
restart v2ray server:&lt;br /&gt;
&lt;br /&gt;
sudo systemctl restart v2ray&lt;br /&gt;
&lt;br /&gt;
== V2RayU Client ==&lt;br /&gt;
Configure -&amp;gt; add v2ray server, input ip/port and client id.&lt;br /&gt;
&lt;br /&gt;
Git ssh over socks proxy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# vim ~/.ssh/config&lt;br /&gt;
Host github.com&lt;br /&gt;
HostName github.com&lt;br /&gt;
User git&lt;br /&gt;
ProxyCommand nc -v -x 127.0.0.1:1080 %h %p&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=V2Ray_global_proxy&amp;diff=5135</id>
		<title>V2Ray global proxy</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=V2Ray_global_proxy&amp;diff=5135"/>
		<updated>2025-10-05T09:42:40Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Basic Config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Install V2Ray (Server side) =&lt;br /&gt;
== Install ==&lt;br /&gt;
https://github.com/v2fly/fhs-install-v2ray&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# switch to root user and then install&lt;br /&gt;
sudo su -&lt;br /&gt;
&lt;br /&gt;
bash &amp;lt;(curl -L https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh)&lt;br /&gt;
systemctl enable v2ray&lt;br /&gt;
systemctl start v2ray&lt;br /&gt;
&lt;br /&gt;
bash &amp;lt;(curl -L https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-dat-release.sh)&lt;br /&gt;
&lt;br /&gt;
v2ray version&lt;br /&gt;
V2Ray 5.22.0 (V2Fly, a community-driven edition of V2Ray.) Custom (go1.23.2 linux/amd64)&lt;br /&gt;
A unified platform for anti-censorship.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Basic Config ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ systemctl status v2ray&lt;br /&gt;
● v2ray.service - V2Ray Service&lt;br /&gt;
     Loaded: loaded (/etc/systemd/system/v2ray.service; enabled; preset: enable&amp;gt;&lt;br /&gt;
    Drop-In: /etc/systemd/system/v2ray.service.d&lt;br /&gt;
             └─10-donot_touch_single_conf.conf&lt;br /&gt;
     Active: active (running) since Fri 2025-04-18 14:11:22 UTC; 5 months 17 da&amp;gt;&lt;br /&gt;
       Docs: https://www.v2fly.org/&lt;br /&gt;
   Main PID: 719 (v2ray)&lt;br /&gt;
      Tasks: 14 (limit: 9441)&lt;br /&gt;
     Memory: 35.8M (peak: 103.4M)&lt;br /&gt;
        CPU: 8h 56min 41.528s&lt;br /&gt;
     CGroup: /system.slice/v2ray.service&lt;br /&gt;
             └─719 /usr/local/bin/v2ray run -config /usr/local/etc/v2ray/config&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: some journal files were not opened due to insufficient permissions.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/usr/local/etc/v2ray/config.json&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;inbounds&amp;quot;: [{&lt;br /&gt;
    &amp;quot;port&amp;quot;: 10086,&lt;br /&gt;
    &amp;quot;protocol&amp;quot;: &amp;quot;vmess&amp;quot;,&lt;br /&gt;
    &amp;quot;settings&amp;quot;: {&lt;br /&gt;
      &amp;quot;clients&amp;quot;: [{ &amp;quot;id&amp;quot;: &amp;quot;b831381d-6324-4d53-ad4f-8cda48b30811&amp;quot; }]&lt;br /&gt;
    }&lt;br /&gt;
  }],&lt;br /&gt;
  &amp;quot;outbounds&amp;quot;: [{&lt;br /&gt;
    &amp;quot;protocol&amp;quot;: &amp;quot;freedom&amp;quot;,&lt;br /&gt;
    &amp;quot;settings&amp;quot;: {}&lt;br /&gt;
  }]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
restart v2ray server:&lt;br /&gt;
&lt;br /&gt;
sudo systemctl restart v2ray&lt;br /&gt;
&lt;br /&gt;
== V2RayU Client ==&lt;br /&gt;
Configure -&amp;gt; add v2ray server, input ip/port and client id.&lt;br /&gt;
&lt;br /&gt;
Git ssh over socks proxy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# vim ~/.ssh/config&lt;br /&gt;
Host github.com&lt;br /&gt;
HostName github.com&lt;br /&gt;
User git&lt;br /&gt;
ProxyCommand nc -v -x 127.0.0.1:1080 %h %p&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=V2Ray_global_proxy&amp;diff=5134</id>
		<title>V2Ray global proxy</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=V2Ray_global_proxy&amp;diff=5134"/>
		<updated>2025-10-05T09:41:30Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Install */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Install V2Ray (Server side) =&lt;br /&gt;
== Install ==&lt;br /&gt;
https://github.com/v2fly/fhs-install-v2ray&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# switch to root user and then install&lt;br /&gt;
sudo su -&lt;br /&gt;
&lt;br /&gt;
bash &amp;lt;(curl -L https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh)&lt;br /&gt;
systemctl enable v2ray&lt;br /&gt;
systemctl start v2ray&lt;br /&gt;
&lt;br /&gt;
bash &amp;lt;(curl -L https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-dat-release.sh)&lt;br /&gt;
&lt;br /&gt;
v2ray version&lt;br /&gt;
V2Ray 5.22.0 (V2Fly, a community-driven edition of V2Ray.) Custom (go1.23.2 linux/amd64)&lt;br /&gt;
A unified platform for anti-censorship.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Basic Config ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;inbounds&amp;quot;: [{&lt;br /&gt;
    &amp;quot;port&amp;quot;: 10086,&lt;br /&gt;
    &amp;quot;protocol&amp;quot;: &amp;quot;vmess&amp;quot;,&lt;br /&gt;
    &amp;quot;settings&amp;quot;: {&lt;br /&gt;
      &amp;quot;clients&amp;quot;: [{ &amp;quot;id&amp;quot;: &amp;quot;b831381d-6324-4d53-ad4f-8cda48b30811&amp;quot; }]&lt;br /&gt;
    }&lt;br /&gt;
  }],&lt;br /&gt;
  &amp;quot;outbounds&amp;quot;: [{&lt;br /&gt;
    &amp;quot;protocol&amp;quot;: &amp;quot;freedom&amp;quot;,&lt;br /&gt;
    &amp;quot;settings&amp;quot;: {}&lt;br /&gt;
  }]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
restart v2ray server:&lt;br /&gt;
&lt;br /&gt;
sudo systemctl restart v2ray&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== V2RayU Client ==&lt;br /&gt;
Configure -&amp;gt; add v2ray server, input ip/port and client id.&lt;br /&gt;
&lt;br /&gt;
Git ssh over socks proxy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# vim ~/.ssh/config&lt;br /&gt;
Host github.com&lt;br /&gt;
HostName github.com&lt;br /&gt;
User git&lt;br /&gt;
ProxyCommand nc -v -x 127.0.0.1:1080 %h %p&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5133</id>
		<title>Linux server setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5133"/>
		<updated>2025-10-05T05:37:48Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* ssh config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=System settings =&lt;br /&gt;
== Update system ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt upgrade&lt;br /&gt;
do-release-upgrade&lt;br /&gt;
&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== hostname  ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vim /etc/hostname&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== user ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
adduser ubuntu&lt;br /&gt;
usermod -aG sudo ubuntu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ssh config ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh-copy-id -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&lt;br /&gt;
# vim /etc/ssh/sshd_config&lt;br /&gt;
PermitRootLogin no&lt;br /&gt;
PasswordAuthentication no&lt;br /&gt;
PubkeyAuthentication yes&lt;br /&gt;
&lt;br /&gt;
service ssh restart&lt;br /&gt;
ssh -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ufw==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo ufw enable&lt;br /&gt;
sudo ufw allow 80&lt;br /&gt;
sudo ufw allow 443&lt;br /&gt;
sudo ufw allow 50000&lt;br /&gt;
sudo ufw status numbered&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5132</id>
		<title>Linux server setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5132"/>
		<updated>2025-10-05T05:31:44Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* ssh config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=System settings =&lt;br /&gt;
== Update system ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt upgrade&lt;br /&gt;
do-release-upgrade&lt;br /&gt;
&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== hostname  ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vim /etc/hostname&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== user ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
adduser ubuntu&lt;br /&gt;
usermod -aG sudo ubuntu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ssh config ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh-copy-id -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&lt;br /&gt;
# vim /etc/ssh/sshd_config&lt;br /&gt;
PermitRootLogin no&lt;br /&gt;
PasswordAuthentication no&lt;br /&gt;
PubkeyAuthentication yes&lt;br /&gt;
&lt;br /&gt;
service ssh restart&lt;br /&gt;
ssh -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5131</id>
		<title>Linux server setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5131"/>
		<updated>2025-10-05T05:27:10Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* ssh config */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=System settings =&lt;br /&gt;
== Update system ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt upgrade&lt;br /&gt;
do-release-upgrade&lt;br /&gt;
&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== hostname  ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vim /etc/hostname&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== user ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
adduser ubuntu&lt;br /&gt;
usermod -aG sudo ubuntu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ssh config ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh-copy-id -p 50000 ubuntu@12.98.23.12&lt;br /&gt;
&lt;br /&gt;
# vim /etc/ssh/sshd_config&lt;br /&gt;
PermitRootLogin no&lt;br /&gt;
PasswordAuthentication no&lt;br /&gt;
PubkeyAuthentication yes&lt;br /&gt;
&lt;br /&gt;
service ssh restart&lt;br /&gt;
ssh -p 50000 root@12.98.23.12&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5130</id>
		<title>Linux server setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5130"/>
		<updated>2025-10-05T05:25:52Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* hostname */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=System settings =&lt;br /&gt;
== Update system ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt upgrade&lt;br /&gt;
do-release-upgrade&lt;br /&gt;
&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== hostname  ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vim /etc/hostname&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== user ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
adduser ubuntu&lt;br /&gt;
usermod -aG sudo ubuntu&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ssh config ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh-copy-id -p 50000 root@12.98.23.12&lt;br /&gt;
&lt;br /&gt;
# vim /etc/ssh/sshd_config&lt;br /&gt;
PubkeyAuthentication yes&lt;br /&gt;
&lt;br /&gt;
service ssh restart&lt;br /&gt;
ssh -p 50000 root@12.98.23.12&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5129</id>
		<title>Linux server setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5129"/>
		<updated>2025-10-05T05:22:52Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* System settings */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=System settings =&lt;br /&gt;
== Update system ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt upgrade&lt;br /&gt;
do-release-upgrade&lt;br /&gt;
&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== hostname ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vim /etc/hostname&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ssh config ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh-copy-id -p 50000 root@12.98.23.12&lt;br /&gt;
&lt;br /&gt;
# vim /etc/ssh/sshd_config&lt;br /&gt;
PubkeyAuthentication yes&lt;br /&gt;
&lt;br /&gt;
service ssh restart&lt;br /&gt;
ssh -p 50000 root@12.98.23.12&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5128</id>
		<title>Linux server setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5128"/>
		<updated>2025-10-05T03:27:54Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=System settings =&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt update&lt;br /&gt;
sudo apt upgrade&lt;br /&gt;
do-release-upgrade&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5127</id>
		<title>Linux server setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Linux_server_setup&amp;diff=5127"/>
		<updated>2025-10-05T03:17:04Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​创建页面，内容为“   Category:Linux/Unix”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Linux/Unix]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=%E6%9C%AA%E6%9D%A5%E4%BD%8F%E6%89%80%E8%AE%BE%E8%AE%A1&amp;diff=5126</id>
		<title>未来住所设计</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=%E6%9C%AA%E6%9D%A5%E4%BD%8F%E6%89%80%E8%AE%BE%E8%AE%A1&amp;diff=5126"/>
		<updated>2025-09-08T14:12:53Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= 装修 =&lt;br /&gt;
==布局==&lt;br /&gt;
==水电==&lt;br /&gt;
==网络==&lt;br /&gt;
&lt;br /&gt;
=区域设计=&lt;br /&gt;
== 书房/工作室==&lt;br /&gt;
== 客厅==&lt;br /&gt;
== 卧室==&lt;br /&gt;
== 厨房==&lt;br /&gt;
== 洗手间==&lt;br /&gt;
== 阳台==&lt;br /&gt;
&lt;br /&gt;
= 功能 =&lt;br /&gt;
== 太阳能电站 ==&lt;br /&gt;
== 机房 ==&lt;br /&gt;
== NAS ==&lt;br /&gt;
== 家庭影院==&lt;br /&gt;
== HIFI ==&lt;br /&gt;
&lt;br /&gt;
== 生态系统==&lt;br /&gt;
&lt;br /&gt;
= 创意 =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:House Design]]&lt;br /&gt;
[[Category:Reminder]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=%E6%9C%AA%E6%9D%A5%E4%BD%8F%E6%89%80%E8%AE%BE%E8%AE%A1&amp;diff=5125</id>
		<title>未来住所设计</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=%E6%9C%AA%E6%9D%A5%E4%BD%8F%E6%89%80%E8%AE%BE%E8%AE%A1&amp;diff=5125"/>
		<updated>2025-09-08T14:09:52Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* 客厅 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= 装修 =&lt;br /&gt;
==布局==&lt;br /&gt;
==水电==&lt;br /&gt;
==网络==&lt;br /&gt;
&lt;br /&gt;
=区域设计=&lt;br /&gt;
== 书房/工作室==&lt;br /&gt;
== 客厅==&lt;br /&gt;
&lt;br /&gt;
== 卧室==&lt;br /&gt;
== 厨房==&lt;br /&gt;
== 洗手间==&lt;br /&gt;
== 阳台==&lt;br /&gt;
&lt;br /&gt;
= 创意 =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:House Design]]&lt;br /&gt;
[[Category:Reminder]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=%E6%9C%AA%E6%9D%A5%E4%BD%8F%E6%89%80%E8%AE%BE%E8%AE%A1&amp;diff=5124</id>
		<title>未来住所设计</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=%E6%9C%AA%E6%9D%A5%E4%BD%8F%E6%89%80%E8%AE%BE%E8%AE%A1&amp;diff=5124"/>
		<updated>2025-09-08T14:09:19Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​创建页面，内容为“= 装修 = ==布局== ==水电== ==网络==  =区域设计= == 书房/工作室== == 客厅== == 卧室== == 厨房== == 洗手间== == 阳台==  = 创意 =    Category:House Design Category:Reminder”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= 装修 =&lt;br /&gt;
==布局==&lt;br /&gt;
==水电==&lt;br /&gt;
==网络==&lt;br /&gt;
&lt;br /&gt;
=区域设计=&lt;br /&gt;
== 书房/工作室==&lt;br /&gt;
== 客厅==&lt;br /&gt;
== 卧室==&lt;br /&gt;
== 厨房==&lt;br /&gt;
== 洗手间==&lt;br /&gt;
== 阳台==&lt;br /&gt;
&lt;br /&gt;
= 创意 =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:House Design]]&lt;br /&gt;
[[Category:Reminder]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=DDD_guide&amp;diff=5123</id>
		<title>DDD guide</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=DDD_guide&amp;diff=5123"/>
		<updated>2025-08-26T12:41:02Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Layers in DDD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Domain-Driven Design (DDD) Guide =&lt;br /&gt;
&lt;br /&gt;
This guide provides an overview of key concepts and best practices for implementing Domain-Driven Design (DDD), focusing on the separation of concerns between the domain model, repository, and persistence layer.&lt;br /&gt;
&lt;br /&gt;
== Key Principles of DDD ==&lt;br /&gt;
* &#039;&#039;&#039;Focus on the Domain&#039;&#039;&#039;:&lt;br /&gt;
** The domain model represents the core business logic and rules.&lt;br /&gt;
** It should be independent of technical concerns like persistence or frameworks.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Separation of Concerns&#039;&#039;&#039;:&lt;br /&gt;
** Divide responsibilities between the domain layer, application layer, and infrastructure layer.&lt;br /&gt;
** Keep the domain layer free from infrastructure dependencies.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Ubiquitous Language&#039;&#039;&#039;:&lt;br /&gt;
** Use a shared language between developers and domain experts to ensure clarity and alignment.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Repository Pattern&#039;&#039;&#039;:&lt;br /&gt;
** Use repositories to abstract persistence logic and provide access to domain objects.&lt;br /&gt;
&lt;br /&gt;
== Layers in DDD ==&lt;br /&gt;
&amp;lt;ref&amp;gt; https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/ddd-oriented-microservice&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
com.example.todo&lt;br /&gt;
├── application&lt;br /&gt;
│   ├── service&lt;br /&gt;
│   └── dto&lt;br /&gt;
├── domain&lt;br /&gt;
│   ├── model&lt;br /&gt;
│   ├── repository&lt;br /&gt;
│   └── service&lt;br /&gt;
├── infrastructure&lt;br /&gt;
│   ├── persistence&lt;br /&gt;
│   ├── messaging&lt;br /&gt;
│   └── configuration&lt;br /&gt;
└── interface&lt;br /&gt;
    ├── controller&lt;br /&gt;
    └── mapper&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dependency rule&amp;lt;ref&amp;gt;https://khalilstemmler.com/wiki/dependency-rule/&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
[[Image:ddd-dependency-rule.svg|600px]]&lt;br /&gt;
&lt;br /&gt;
=== Domain Layer ===&lt;br /&gt;
The domain layer contains the core business logic and domain models.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Responsibilities&#039;&#039;&#039;:&lt;br /&gt;
** Encapsulate business rules and behavior.&lt;br /&gt;
** Represent the core concepts of the domain.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Key Components&#039;&#039;&#039;:&lt;br /&gt;
** &#039;&#039;&#039;Entities&#039;&#039;&#039;: Objects with a unique identity (e.g., `Todo`).&lt;br /&gt;
** &#039;&#039;&#039;Value Objects&#039;&#039;&#039;: Immutable objects that represent a concept (e.g., `TodoId`).&lt;br /&gt;
** &#039;&#039;&#039;Aggregates&#039;&#039;&#039;: A cluster of domain objects treated as a single unit.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Best Practices&#039;&#039;&#039;:&lt;br /&gt;
** Avoid adding persistence-related methods (e.g., `save()` or `delete()`) to domain models.&lt;br /&gt;
** Keep domain models focused on business logic.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Example&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class Todo {&lt;br /&gt;
    private TodoId id;&lt;br /&gt;
    private String title;&lt;br /&gt;
    private String description;&lt;br /&gt;
    private boolean completed;&lt;br /&gt;
&lt;br /&gt;
    public Todo(TodoId id, String title, String description) {&lt;br /&gt;
        this.id = id;&lt;br /&gt;
        this.title = title;&lt;br /&gt;
        this.description = description;&lt;br /&gt;
        this.completed = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public void markAsCompleted() {&lt;br /&gt;
        this.completed = true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Getters and setters&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Application Layer ===&lt;br /&gt;
The application layer coordinates use cases and orchestrates interactions between the domain and infrastructure layers.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Responsibilities&#039;&#039;&#039;:&lt;br /&gt;
** Handle application-specific logic (e.g., workflows, use cases).&lt;br /&gt;
** Delegate persistence to repositories.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Example&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class TodoApplicationService {&lt;br /&gt;
    private final TodoRepository todoRepository;&lt;br /&gt;
&lt;br /&gt;
    public TodoApplicationService(TodoRepository todoRepository) {&lt;br /&gt;
        this.todoRepository = todoRepository;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public void createTodo(String title, String description) {&lt;br /&gt;
        Todo todo = new Todo(new TodoId(UUID.randomUUID()), title, description);&lt;br /&gt;
        todoRepository.save(todo);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Infrastructure Layer ===&lt;br /&gt;
The infrastructure layer handles technical concerns like persistence, messaging, and external APIs.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Responsibilities&#039;&#039;&#039;:&lt;br /&gt;
** Implement repository interfaces defined in the domain layer.&lt;br /&gt;
** Map between domain models and database entities.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Example&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@Repository&lt;br /&gt;
public class JpaTodoRepository implements TodoRepository {&lt;br /&gt;
    private final SpringDataTodoEntityRepository entityRepository;&lt;br /&gt;
&lt;br /&gt;
    public JpaTodoRepository(SpringDataTodoEntityRepository entityRepository) {&lt;br /&gt;
        this.entityRepository = entityRepository;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void save(Todo todo) {&lt;br /&gt;
        TodoEntity entity = mapToEntity(todo);&lt;br /&gt;
        entityRepository.save(entity);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public Optional&amp;lt;Todo&amp;gt; findById(TodoId id) {&lt;br /&gt;
        return entityRepository.findById(id.getValue())&lt;br /&gt;
                               .map(this::mapToDomain);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    private TodoEntity mapToEntity(Todo todo) {&lt;br /&gt;
        TodoEntity entity = new TodoEntity();&lt;br /&gt;
        entity.setId(todo.getId().getValue());&lt;br /&gt;
        entity.setTitle(todo.getTitle());&lt;br /&gt;
        entity.setDescription(todo.getDescription());&lt;br /&gt;
        entity.setCompleted(todo.isCompleted());&lt;br /&gt;
        return entity;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    private Todo mapToDomain(TodoEntity entity) {&lt;br /&gt;
        return new Todo(&lt;br /&gt;
            new TodoId(entity.getId()),&lt;br /&gt;
            entity.getTitle(),&lt;br /&gt;
            entity.getDescription(),&lt;br /&gt;
            entity.isCompleted()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Repository Pattern ==&lt;br /&gt;
The repository pattern abstracts persistence logic and provides access to domain objects.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Interface in the Domain Layer&#039;&#039;&#039;:&lt;br /&gt;
** Define the contract for persistence using domain models.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public interface TodoRepository {&lt;br /&gt;
    void save(Todo todo);&lt;br /&gt;
    Optional&amp;lt;Todo&amp;gt; findById(TodoId id);&lt;br /&gt;
    List&amp;lt;Todo&amp;gt; findAll();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Implementation in the Infrastructure Layer&#039;&#039;&#039;:&lt;br /&gt;
** Implement the repository interface using database-specific entities and persistence mechanisms.&lt;br /&gt;
&lt;br /&gt;
== Mapping Between Domain Models and Database Entities ==&lt;br /&gt;
To keep the domain layer independent of persistence, map between domain models and database entities in the infrastructure layer.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Domain Model&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class Todo {&lt;br /&gt;
    private TodoId id;&lt;br /&gt;
    private String title;&lt;br /&gt;
    private String description;&lt;br /&gt;
    private boolean completed;&lt;br /&gt;
&lt;br /&gt;
    // Business logic&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Database Entity&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@Entity&lt;br /&gt;
@Table(name = &amp;quot;todos&amp;quot;)&lt;br /&gt;
public class TodoEntity {&lt;br /&gt;
    @Id&lt;br /&gt;
    @GeneratedValue(strategy = GenerationType.IDENTITY)&lt;br /&gt;
    private Long id;&lt;br /&gt;
&lt;br /&gt;
    private String title;&lt;br /&gt;
    private String description;&lt;br /&gt;
    private boolean completed;&lt;br /&gt;
&lt;br /&gt;
    // Getters and setters&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices ==&lt;br /&gt;
* Use &#039;&#039;&#039;domain models&#039;&#039;&#039; in the repository interface, not database entities.&lt;br /&gt;
* Keep the domain layer free from persistence concerns.&lt;br /&gt;
* Use mappers (manual or libraries like MapStruct) to convert between domain models and database entities.&lt;br /&gt;
* Avoid adding persistence-related methods (e.g., `save()`) to domain models.&lt;br /&gt;
* Use the &#039;&#039;&#039;Unit of Work&#039;&#039;&#039; or &#039;&#039;&#039;event-driven mechanisms&#039;&#039;&#039; for automatic persistence if needed.&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
* The domain layer focuses on business logic and uses repositories to abstract persistence.&lt;br /&gt;
* The infrastructure layer handles persistence and maps between domain models and database entities.&lt;br /&gt;
* Keep the domain layer decoupled from technical concerns to ensure clean, maintainable, and testable code.&lt;br /&gt;
&lt;br /&gt;
=FAQ =&lt;br /&gt;
== Difference between repository and persistence ==&lt;br /&gt;
The repository in the domain layer and the persistence layer in the infrastructure serve different purposes and are part of the separation of concerns in DDD. &lt;br /&gt;
&lt;br /&gt;
* The repository in the domain layer is an abstraction (interface) that defines how the domain interacts with persistence.&lt;br /&gt;
* The persistence layer in the infrastructure is the implementation of that abstraction, handling the actual database operations.&lt;br /&gt;
&lt;br /&gt;
== Should I use domain model or database entity in repository? ==&lt;br /&gt;
In the repository interface (defined in the domain layer), you should use domain models because the repository is part of the domain layer and should work with the core business concepts. However, in the repository implementation (in the infrastructure layer), you can map between domain models and database entities to handle persistence.&lt;br /&gt;
&lt;br /&gt;
== Should I have a save() method in domain model ==&lt;br /&gt;
&lt;br /&gt;
No, the domain model (Todo) should not have a save() method. In Domain-Driven Design (DDD), the domain model is responsible for encapsulating business logic and representing the core concepts of the domain. It should not be concerned with persistence or infrastructure details like saving to a database.&lt;br /&gt;
&lt;br /&gt;
== Should I handle messages in repository? ==&lt;br /&gt;
&lt;br /&gt;
Message brokers like Kafka, RabbitMQ, or others are not persistence mechanisms in the traditional sense but are instead used for communication and event-driven architectures. Therefore, creating a repository for a message broker is generally not recommended. Instead, you should handle message brokers in the application layer or infrastructure layer.&lt;br /&gt;
&lt;br /&gt;
* Do not create a repository for message brokers like Kafka.&lt;br /&gt;
* Use the application layer to handle message publishing/consuming.&lt;br /&gt;
* Abstract the message broker interaction using interfaces and implement them in the infrastructure layer.&lt;br /&gt;
* Leverage domain events to integrate with message brokers in an event-driven architecture.&lt;br /&gt;
&lt;br /&gt;
Whether you should create a repository for Redis depends on how you are using Redis in your application.&lt;br /&gt;
&lt;br /&gt;
* Use a repository for Redis only if it is a primary data store for domain entities.&lt;br /&gt;
* For caching, use decorators or handle it in the infrastructure layer.&lt;br /&gt;
* For non-domain purposes (e.g., rate limiting, session storage), handle Redis interactions directly in the infrastructure or application layer.&lt;br /&gt;
* Always keep the domain layer free of Redis-specific logic to maintain separation of concerns.&lt;br /&gt;
&lt;br /&gt;
== Do I need a service layer? ==&lt;br /&gt;
Whether you need a service layer depends on the complexity of your application and how you structure your code. In Domain-Driven Design (DDD), the service layer (often referred to as the application layer) plays an important role in coordinating use cases and workflows. &lt;br /&gt;
&lt;br /&gt;
You might skip the service layer if:&lt;br /&gt;
&lt;br /&gt;
* Your application is simple&lt;br /&gt;
* Your domain logic is self-contained&lt;br /&gt;
&lt;br /&gt;
[[Category:DDD]]&lt;br /&gt;
[[Category:MicroService]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=%E6%96%87%E4%BB%B6:Ddd-dependency-rule.svg&amp;diff=5122</id>
		<title>文件:Ddd-dependency-rule.svg</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=%E6%96%87%E4%BB%B6:Ddd-dependency-rule.svg&amp;diff=5122"/>
		<updated>2025-08-26T12:40:31Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=DDD_guide&amp;diff=5121</id>
		<title>DDD guide</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=DDD_guide&amp;diff=5121"/>
		<updated>2025-08-26T12:40:19Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Layers in DDD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Domain-Driven Design (DDD) Guide =&lt;br /&gt;
&lt;br /&gt;
This guide provides an overview of key concepts and best practices for implementing Domain-Driven Design (DDD), focusing on the separation of concerns between the domain model, repository, and persistence layer.&lt;br /&gt;
&lt;br /&gt;
== Key Principles of DDD ==&lt;br /&gt;
* &#039;&#039;&#039;Focus on the Domain&#039;&#039;&#039;:&lt;br /&gt;
** The domain model represents the core business logic and rules.&lt;br /&gt;
** It should be independent of technical concerns like persistence or frameworks.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Separation of Concerns&#039;&#039;&#039;:&lt;br /&gt;
** Divide responsibilities between the domain layer, application layer, and infrastructure layer.&lt;br /&gt;
** Keep the domain layer free from infrastructure dependencies.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Ubiquitous Language&#039;&#039;&#039;:&lt;br /&gt;
** Use a shared language between developers and domain experts to ensure clarity and alignment.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Repository Pattern&#039;&#039;&#039;:&lt;br /&gt;
** Use repositories to abstract persistence logic and provide access to domain objects.&lt;br /&gt;
&lt;br /&gt;
== Layers in DDD ==&lt;br /&gt;
&amp;lt;ref&amp;gt; https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/ddd-oriented-microservice&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
com.example.todo&lt;br /&gt;
├── application&lt;br /&gt;
│   ├── service&lt;br /&gt;
│   └── dto&lt;br /&gt;
├── domain&lt;br /&gt;
│   ├── model&lt;br /&gt;
│   ├── repository&lt;br /&gt;
│   └── service&lt;br /&gt;
├── infrastructure&lt;br /&gt;
│   ├── persistence&lt;br /&gt;
│   ├── messaging&lt;br /&gt;
│   └── configuration&lt;br /&gt;
└── interface&lt;br /&gt;
    ├── controller&lt;br /&gt;
    └── mapper&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dependency rule:&lt;br /&gt;
&lt;br /&gt;
[[Image:ddd-dependency-rule.svg|600px]]&lt;br /&gt;
&lt;br /&gt;
=== Domain Layer ===&lt;br /&gt;
The domain layer contains the core business logic and domain models.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Responsibilities&#039;&#039;&#039;:&lt;br /&gt;
** Encapsulate business rules and behavior.&lt;br /&gt;
** Represent the core concepts of the domain.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Key Components&#039;&#039;&#039;:&lt;br /&gt;
** &#039;&#039;&#039;Entities&#039;&#039;&#039;: Objects with a unique identity (e.g., `Todo`).&lt;br /&gt;
** &#039;&#039;&#039;Value Objects&#039;&#039;&#039;: Immutable objects that represent a concept (e.g., `TodoId`).&lt;br /&gt;
** &#039;&#039;&#039;Aggregates&#039;&#039;&#039;: A cluster of domain objects treated as a single unit.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Best Practices&#039;&#039;&#039;:&lt;br /&gt;
** Avoid adding persistence-related methods (e.g., `save()` or `delete()`) to domain models.&lt;br /&gt;
** Keep domain models focused on business logic.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Example&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class Todo {&lt;br /&gt;
    private TodoId id;&lt;br /&gt;
    private String title;&lt;br /&gt;
    private String description;&lt;br /&gt;
    private boolean completed;&lt;br /&gt;
&lt;br /&gt;
    public Todo(TodoId id, String title, String description) {&lt;br /&gt;
        this.id = id;&lt;br /&gt;
        this.title = title;&lt;br /&gt;
        this.description = description;&lt;br /&gt;
        this.completed = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public void markAsCompleted() {&lt;br /&gt;
        this.completed = true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Getters and setters&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Application Layer ===&lt;br /&gt;
The application layer coordinates use cases and orchestrates interactions between the domain and infrastructure layers.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Responsibilities&#039;&#039;&#039;:&lt;br /&gt;
** Handle application-specific logic (e.g., workflows, use cases).&lt;br /&gt;
** Delegate persistence to repositories.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Example&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class TodoApplicationService {&lt;br /&gt;
    private final TodoRepository todoRepository;&lt;br /&gt;
&lt;br /&gt;
    public TodoApplicationService(TodoRepository todoRepository) {&lt;br /&gt;
        this.todoRepository = todoRepository;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public void createTodo(String title, String description) {&lt;br /&gt;
        Todo todo = new Todo(new TodoId(UUID.randomUUID()), title, description);&lt;br /&gt;
        todoRepository.save(todo);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Infrastructure Layer ===&lt;br /&gt;
The infrastructure layer handles technical concerns like persistence, messaging, and external APIs.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Responsibilities&#039;&#039;&#039;:&lt;br /&gt;
** Implement repository interfaces defined in the domain layer.&lt;br /&gt;
** Map between domain models and database entities.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Example&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@Repository&lt;br /&gt;
public class JpaTodoRepository implements TodoRepository {&lt;br /&gt;
    private final SpringDataTodoEntityRepository entityRepository;&lt;br /&gt;
&lt;br /&gt;
    public JpaTodoRepository(SpringDataTodoEntityRepository entityRepository) {&lt;br /&gt;
        this.entityRepository = entityRepository;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void save(Todo todo) {&lt;br /&gt;
        TodoEntity entity = mapToEntity(todo);&lt;br /&gt;
        entityRepository.save(entity);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public Optional&amp;lt;Todo&amp;gt; findById(TodoId id) {&lt;br /&gt;
        return entityRepository.findById(id.getValue())&lt;br /&gt;
                               .map(this::mapToDomain);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    private TodoEntity mapToEntity(Todo todo) {&lt;br /&gt;
        TodoEntity entity = new TodoEntity();&lt;br /&gt;
        entity.setId(todo.getId().getValue());&lt;br /&gt;
        entity.setTitle(todo.getTitle());&lt;br /&gt;
        entity.setDescription(todo.getDescription());&lt;br /&gt;
        entity.setCompleted(todo.isCompleted());&lt;br /&gt;
        return entity;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    private Todo mapToDomain(TodoEntity entity) {&lt;br /&gt;
        return new Todo(&lt;br /&gt;
            new TodoId(entity.getId()),&lt;br /&gt;
            entity.getTitle(),&lt;br /&gt;
            entity.getDescription(),&lt;br /&gt;
            entity.isCompleted()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Repository Pattern ==&lt;br /&gt;
The repository pattern abstracts persistence logic and provides access to domain objects.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Interface in the Domain Layer&#039;&#039;&#039;:&lt;br /&gt;
** Define the contract for persistence using domain models.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public interface TodoRepository {&lt;br /&gt;
    void save(Todo todo);&lt;br /&gt;
    Optional&amp;lt;Todo&amp;gt; findById(TodoId id);&lt;br /&gt;
    List&amp;lt;Todo&amp;gt; findAll();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Implementation in the Infrastructure Layer&#039;&#039;&#039;:&lt;br /&gt;
** Implement the repository interface using database-specific entities and persistence mechanisms.&lt;br /&gt;
&lt;br /&gt;
== Mapping Between Domain Models and Database Entities ==&lt;br /&gt;
To keep the domain layer independent of persistence, map between domain models and database entities in the infrastructure layer.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Domain Model&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class Todo {&lt;br /&gt;
    private TodoId id;&lt;br /&gt;
    private String title;&lt;br /&gt;
    private String description;&lt;br /&gt;
    private boolean completed;&lt;br /&gt;
&lt;br /&gt;
    // Business logic&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Database Entity&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@Entity&lt;br /&gt;
@Table(name = &amp;quot;todos&amp;quot;)&lt;br /&gt;
public class TodoEntity {&lt;br /&gt;
    @Id&lt;br /&gt;
    @GeneratedValue(strategy = GenerationType.IDENTITY)&lt;br /&gt;
    private Long id;&lt;br /&gt;
&lt;br /&gt;
    private String title;&lt;br /&gt;
    private String description;&lt;br /&gt;
    private boolean completed;&lt;br /&gt;
&lt;br /&gt;
    // Getters and setters&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices ==&lt;br /&gt;
* Use &#039;&#039;&#039;domain models&#039;&#039;&#039; in the repository interface, not database entities.&lt;br /&gt;
* Keep the domain layer free from persistence concerns.&lt;br /&gt;
* Use mappers (manual or libraries like MapStruct) to convert between domain models and database entities.&lt;br /&gt;
* Avoid adding persistence-related methods (e.g., `save()`) to domain models.&lt;br /&gt;
* Use the &#039;&#039;&#039;Unit of Work&#039;&#039;&#039; or &#039;&#039;&#039;event-driven mechanisms&#039;&#039;&#039; for automatic persistence if needed.&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
* The domain layer focuses on business logic and uses repositories to abstract persistence.&lt;br /&gt;
* The infrastructure layer handles persistence and maps between domain models and database entities.&lt;br /&gt;
* Keep the domain layer decoupled from technical concerns to ensure clean, maintainable, and testable code.&lt;br /&gt;
&lt;br /&gt;
=FAQ =&lt;br /&gt;
== Difference between repository and persistence ==&lt;br /&gt;
The repository in the domain layer and the persistence layer in the infrastructure serve different purposes and are part of the separation of concerns in DDD. &lt;br /&gt;
&lt;br /&gt;
* The repository in the domain layer is an abstraction (interface) that defines how the domain interacts with persistence.&lt;br /&gt;
* The persistence layer in the infrastructure is the implementation of that abstraction, handling the actual database operations.&lt;br /&gt;
&lt;br /&gt;
== Should I use domain model or database entity in repository? ==&lt;br /&gt;
In the repository interface (defined in the domain layer), you should use domain models because the repository is part of the domain layer and should work with the core business concepts. However, in the repository implementation (in the infrastructure layer), you can map between domain models and database entities to handle persistence.&lt;br /&gt;
&lt;br /&gt;
== Should I have a save() method in domain model ==&lt;br /&gt;
&lt;br /&gt;
No, the domain model (Todo) should not have a save() method. In Domain-Driven Design (DDD), the domain model is responsible for encapsulating business logic and representing the core concepts of the domain. It should not be concerned with persistence or infrastructure details like saving to a database.&lt;br /&gt;
&lt;br /&gt;
== Should I handle messages in repository? ==&lt;br /&gt;
&lt;br /&gt;
Message brokers like Kafka, RabbitMQ, or others are not persistence mechanisms in the traditional sense but are instead used for communication and event-driven architectures. Therefore, creating a repository for a message broker is generally not recommended. Instead, you should handle message brokers in the application layer or infrastructure layer.&lt;br /&gt;
&lt;br /&gt;
* Do not create a repository for message brokers like Kafka.&lt;br /&gt;
* Use the application layer to handle message publishing/consuming.&lt;br /&gt;
* Abstract the message broker interaction using interfaces and implement them in the infrastructure layer.&lt;br /&gt;
* Leverage domain events to integrate with message brokers in an event-driven architecture.&lt;br /&gt;
&lt;br /&gt;
Whether you should create a repository for Redis depends on how you are using Redis in your application.&lt;br /&gt;
&lt;br /&gt;
* Use a repository for Redis only if it is a primary data store for domain entities.&lt;br /&gt;
* For caching, use decorators or handle it in the infrastructure layer.&lt;br /&gt;
* For non-domain purposes (e.g., rate limiting, session storage), handle Redis interactions directly in the infrastructure or application layer.&lt;br /&gt;
* Always keep the domain layer free of Redis-specific logic to maintain separation of concerns.&lt;br /&gt;
&lt;br /&gt;
== Do I need a service layer? ==&lt;br /&gt;
Whether you need a service layer depends on the complexity of your application and how you structure your code. In Domain-Driven Design (DDD), the service layer (often referred to as the application layer) plays an important role in coordinating use cases and workflows. &lt;br /&gt;
&lt;br /&gt;
You might skip the service layer if:&lt;br /&gt;
&lt;br /&gt;
* Your application is simple&lt;br /&gt;
* Your domain logic is self-contained&lt;br /&gt;
&lt;br /&gt;
[[Category:DDD]]&lt;br /&gt;
[[Category:MicroService]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=DDD_guide&amp;diff=5120</id>
		<title>DDD guide</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=DDD_guide&amp;diff=5120"/>
		<updated>2025-08-17T14:00:36Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​/* Layers in DDD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Domain-Driven Design (DDD) Guide =&lt;br /&gt;
&lt;br /&gt;
This guide provides an overview of key concepts and best practices for implementing Domain-Driven Design (DDD), focusing on the separation of concerns between the domain model, repository, and persistence layer.&lt;br /&gt;
&lt;br /&gt;
== Key Principles of DDD ==&lt;br /&gt;
* &#039;&#039;&#039;Focus on the Domain&#039;&#039;&#039;:&lt;br /&gt;
** The domain model represents the core business logic and rules.&lt;br /&gt;
** It should be independent of technical concerns like persistence or frameworks.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Separation of Concerns&#039;&#039;&#039;:&lt;br /&gt;
** Divide responsibilities between the domain layer, application layer, and infrastructure layer.&lt;br /&gt;
** Keep the domain layer free from infrastructure dependencies.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Ubiquitous Language&#039;&#039;&#039;:&lt;br /&gt;
** Use a shared language between developers and domain experts to ensure clarity and alignment.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Repository Pattern&#039;&#039;&#039;:&lt;br /&gt;
** Use repositories to abstract persistence logic and provide access to domain objects.&lt;br /&gt;
&lt;br /&gt;
== Layers in DDD ==&lt;br /&gt;
&amp;lt;ref&amp;gt; https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/ddd-oriented-microservice&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
com.example.todo&lt;br /&gt;
├── application&lt;br /&gt;
│   ├── service&lt;br /&gt;
│   └── dto&lt;br /&gt;
├── domain&lt;br /&gt;
│   ├── model&lt;br /&gt;
│   ├── repository&lt;br /&gt;
│   └── service&lt;br /&gt;
├── infrastructure&lt;br /&gt;
│   ├── persistence&lt;br /&gt;
│   ├── messaging&lt;br /&gt;
│   └── configuration&lt;br /&gt;
└── interface&lt;br /&gt;
    ├── controller&lt;br /&gt;
    └── mapper&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Domain Layer ===&lt;br /&gt;
The domain layer contains the core business logic and domain models.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Responsibilities&#039;&#039;&#039;:&lt;br /&gt;
** Encapsulate business rules and behavior.&lt;br /&gt;
** Represent the core concepts of the domain.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Key Components&#039;&#039;&#039;:&lt;br /&gt;
** &#039;&#039;&#039;Entities&#039;&#039;&#039;: Objects with a unique identity (e.g., `Todo`).&lt;br /&gt;
** &#039;&#039;&#039;Value Objects&#039;&#039;&#039;: Immutable objects that represent a concept (e.g., `TodoId`).&lt;br /&gt;
** &#039;&#039;&#039;Aggregates&#039;&#039;&#039;: A cluster of domain objects treated as a single unit.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Best Practices&#039;&#039;&#039;:&lt;br /&gt;
** Avoid adding persistence-related methods (e.g., `save()` or `delete()`) to domain models.&lt;br /&gt;
** Keep domain models focused on business logic.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Example&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class Todo {&lt;br /&gt;
    private TodoId id;&lt;br /&gt;
    private String title;&lt;br /&gt;
    private String description;&lt;br /&gt;
    private boolean completed;&lt;br /&gt;
&lt;br /&gt;
    public Todo(TodoId id, String title, String description) {&lt;br /&gt;
        this.id = id;&lt;br /&gt;
        this.title = title;&lt;br /&gt;
        this.description = description;&lt;br /&gt;
        this.completed = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public void markAsCompleted() {&lt;br /&gt;
        this.completed = true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Getters and setters&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Application Layer ===&lt;br /&gt;
The application layer coordinates use cases and orchestrates interactions between the domain and infrastructure layers.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Responsibilities&#039;&#039;&#039;:&lt;br /&gt;
** Handle application-specific logic (e.g., workflows, use cases).&lt;br /&gt;
** Delegate persistence to repositories.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Example&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class TodoApplicationService {&lt;br /&gt;
    private final TodoRepository todoRepository;&lt;br /&gt;
&lt;br /&gt;
    public TodoApplicationService(TodoRepository todoRepository) {&lt;br /&gt;
        this.todoRepository = todoRepository;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public void createTodo(String title, String description) {&lt;br /&gt;
        Todo todo = new Todo(new TodoId(UUID.randomUUID()), title, description);&lt;br /&gt;
        todoRepository.save(todo);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Infrastructure Layer ===&lt;br /&gt;
The infrastructure layer handles technical concerns like persistence, messaging, and external APIs.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Responsibilities&#039;&#039;&#039;:&lt;br /&gt;
** Implement repository interfaces defined in the domain layer.&lt;br /&gt;
** Map between domain models and database entities.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Example&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@Repository&lt;br /&gt;
public class JpaTodoRepository implements TodoRepository {&lt;br /&gt;
    private final SpringDataTodoEntityRepository entityRepository;&lt;br /&gt;
&lt;br /&gt;
    public JpaTodoRepository(SpringDataTodoEntityRepository entityRepository) {&lt;br /&gt;
        this.entityRepository = entityRepository;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void save(Todo todo) {&lt;br /&gt;
        TodoEntity entity = mapToEntity(todo);&lt;br /&gt;
        entityRepository.save(entity);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public Optional&amp;lt;Todo&amp;gt; findById(TodoId id) {&lt;br /&gt;
        return entityRepository.findById(id.getValue())&lt;br /&gt;
                               .map(this::mapToDomain);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    private TodoEntity mapToEntity(Todo todo) {&lt;br /&gt;
        TodoEntity entity = new TodoEntity();&lt;br /&gt;
        entity.setId(todo.getId().getValue());&lt;br /&gt;
        entity.setTitle(todo.getTitle());&lt;br /&gt;
        entity.setDescription(todo.getDescription());&lt;br /&gt;
        entity.setCompleted(todo.isCompleted());&lt;br /&gt;
        return entity;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    private Todo mapToDomain(TodoEntity entity) {&lt;br /&gt;
        return new Todo(&lt;br /&gt;
            new TodoId(entity.getId()),&lt;br /&gt;
            entity.getTitle(),&lt;br /&gt;
            entity.getDescription(),&lt;br /&gt;
            entity.isCompleted()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Repository Pattern ==&lt;br /&gt;
The repository pattern abstracts persistence logic and provides access to domain objects.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Interface in the Domain Layer&#039;&#039;&#039;:&lt;br /&gt;
** Define the contract for persistence using domain models.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public interface TodoRepository {&lt;br /&gt;
    void save(Todo todo);&lt;br /&gt;
    Optional&amp;lt;Todo&amp;gt; findById(TodoId id);&lt;br /&gt;
    List&amp;lt;Todo&amp;gt; findAll();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Implementation in the Infrastructure Layer&#039;&#039;&#039;:&lt;br /&gt;
** Implement the repository interface using database-specific entities and persistence mechanisms.&lt;br /&gt;
&lt;br /&gt;
== Mapping Between Domain Models and Database Entities ==&lt;br /&gt;
To keep the domain layer independent of persistence, map between domain models and database entities in the infrastructure layer.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Domain Model&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class Todo {&lt;br /&gt;
    private TodoId id;&lt;br /&gt;
    private String title;&lt;br /&gt;
    private String description;&lt;br /&gt;
    private boolean completed;&lt;br /&gt;
&lt;br /&gt;
    // Business logic&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Database Entity&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
@Entity&lt;br /&gt;
@Table(name = &amp;quot;todos&amp;quot;)&lt;br /&gt;
public class TodoEntity {&lt;br /&gt;
    @Id&lt;br /&gt;
    @GeneratedValue(strategy = GenerationType.IDENTITY)&lt;br /&gt;
    private Long id;&lt;br /&gt;
&lt;br /&gt;
    private String title;&lt;br /&gt;
    private String description;&lt;br /&gt;
    private boolean completed;&lt;br /&gt;
&lt;br /&gt;
    // Getters and setters&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Best Practices ==&lt;br /&gt;
* Use &#039;&#039;&#039;domain models&#039;&#039;&#039; in the repository interface, not database entities.&lt;br /&gt;
* Keep the domain layer free from persistence concerns.&lt;br /&gt;
* Use mappers (manual or libraries like MapStruct) to convert between domain models and database entities.&lt;br /&gt;
* Avoid adding persistence-related methods (e.g., `save()`) to domain models.&lt;br /&gt;
* Use the &#039;&#039;&#039;Unit of Work&#039;&#039;&#039; or &#039;&#039;&#039;event-driven mechanisms&#039;&#039;&#039; for automatic persistence if needed.&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
* The domain layer focuses on business logic and uses repositories to abstract persistence.&lt;br /&gt;
* The infrastructure layer handles persistence and maps between domain models and database entities.&lt;br /&gt;
* Keep the domain layer decoupled from technical concerns to ensure clean, maintainable, and testable code.&lt;br /&gt;
&lt;br /&gt;
=FAQ =&lt;br /&gt;
== Difference between repository and persistence ==&lt;br /&gt;
The repository in the domain layer and the persistence layer in the infrastructure serve different purposes and are part of the separation of concerns in DDD. &lt;br /&gt;
&lt;br /&gt;
* The repository in the domain layer is an abstraction (interface) that defines how the domain interacts with persistence.&lt;br /&gt;
* The persistence layer in the infrastructure is the implementation of that abstraction, handling the actual database operations.&lt;br /&gt;
&lt;br /&gt;
== Should I use domain model or database entity in repository? ==&lt;br /&gt;
In the repository interface (defined in the domain layer), you should use domain models because the repository is part of the domain layer and should work with the core business concepts. However, in the repository implementation (in the infrastructure layer), you can map between domain models and database entities to handle persistence.&lt;br /&gt;
&lt;br /&gt;
== Should I have a save() method in domain model ==&lt;br /&gt;
&lt;br /&gt;
No, the domain model (Todo) should not have a save() method. In Domain-Driven Design (DDD), the domain model is responsible for encapsulating business logic and representing the core concepts of the domain. It should not be concerned with persistence or infrastructure details like saving to a database.&lt;br /&gt;
&lt;br /&gt;
== Should I handle messages in repository? ==&lt;br /&gt;
&lt;br /&gt;
Message brokers like Kafka, RabbitMQ, or others are not persistence mechanisms in the traditional sense but are instead used for communication and event-driven architectures. Therefore, creating a repository for a message broker is generally not recommended. Instead, you should handle message brokers in the application layer or infrastructure layer.&lt;br /&gt;
&lt;br /&gt;
* Do not create a repository for message brokers like Kafka.&lt;br /&gt;
* Use the application layer to handle message publishing/consuming.&lt;br /&gt;
* Abstract the message broker interaction using interfaces and implement them in the infrastructure layer.&lt;br /&gt;
* Leverage domain events to integrate with message brokers in an event-driven architecture.&lt;br /&gt;
&lt;br /&gt;
Whether you should create a repository for Redis depends on how you are using Redis in your application.&lt;br /&gt;
&lt;br /&gt;
* Use a repository for Redis only if it is a primary data store for domain entities.&lt;br /&gt;
* For caching, use decorators or handle it in the infrastructure layer.&lt;br /&gt;
* For non-domain purposes (e.g., rate limiting, session storage), handle Redis interactions directly in the infrastructure or application layer.&lt;br /&gt;
* Always keep the domain layer free of Redis-specific logic to maintain separation of concerns.&lt;br /&gt;
&lt;br /&gt;
== Do I need a service layer? ==&lt;br /&gt;
Whether you need a service layer depends on the complexity of your application and how you structure your code. In Domain-Driven Design (DDD), the service layer (often referred to as the application layer) plays an important role in coordinating use cases and workflows. &lt;br /&gt;
&lt;br /&gt;
You might skip the service layer if:&lt;br /&gt;
&lt;br /&gt;
* Your application is simple&lt;br /&gt;
* Your domain logic is self-contained&lt;br /&gt;
&lt;br /&gt;
[[Category:DDD]]&lt;br /&gt;
[[Category:MicroService]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Ystack&amp;diff=5119</id>
		<title>Ystack</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Ystack&amp;diff=5119"/>
		<updated>2025-08-17T13:45:06Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Services and responsibilities =&lt;br /&gt;
== Auth / Identity (Keycloak) ==&lt;br /&gt;
* Responsibility: Authentication, user identity, SSO, OIDC tokens.&lt;br /&gt;
* Data owned: Keycloak user record (sub), basic profile attributes.&lt;br /&gt;
* Notes: Other services store keycloak_id as foreign reference only.&lt;br /&gt;
&lt;br /&gt;
== Customer Service (customer profile / account)==&lt;br /&gt;
&lt;br /&gt;
* Responsibility: canonical customer profile (name, emails, billing address, company, contact info), payment-customer mapping (e.g., providerCustomerId), invoice delivery preferences, links to internal user records.&lt;br /&gt;
* Data owned: customer table (customer_id, keycloak_id, contact info, provider customer id, metadata).&lt;br /&gt;
* API examples: GET/PUT customer, attach payment method token, list customer’s subscriptions/orders.&lt;br /&gt;
* When to call: read-heavy for CRM and billing, write when profile changes.&lt;br /&gt;
&lt;br /&gt;
== Product / Plan (Catalog) Service ==&lt;br /&gt;
&lt;br /&gt;
* Responsibility: define and manage plans, price points, features, trial configuration, promotions/coupons, entitlements (features JSON).&lt;br /&gt;
* Data owned: plans, SKUs, pricing tiers, feature flags, metadata.&lt;br /&gt;
* Notes: Admin interfaces to create/retire plans; this is authoritative for what users can buy.&lt;br /&gt;
&lt;br /&gt;
== Order / Checkout Service ==&lt;br /&gt;
&lt;br /&gt;
* Responsibility: orchestrate purchase flows and create “orders” as transient/immutable records that represent a purchase attempt. Validate requested plan, pricing, coupons, compute totals and taxes, create provider checkout session or payment intent.&lt;br /&gt;
* Data owned: orders (order_id, customer_id, plan_id, price_at_purchase, status: created/processing/succeeded/failed/expired, idempotency key).&lt;br /&gt;
* Notes: Produces events (OrderCreated, OrderSucceeded, OrderFailed) consumed by Billing/Subscription and Customer services. Should be idempotent (use idempotency key).&lt;br /&gt;
&lt;br /&gt;
== Subscription / Billing Service ==&lt;br /&gt;
&lt;br /&gt;
* Responsibility: map orders into subscriptions, maintain subscription lifecycle (trialing, active, past_due, canceled), reconcile provider subscription state with local state, schedule renewals and billing windows, track current_period_start/end, cancel_at_period_end flags.&lt;br /&gt;
* Data owned: subscriptions table, subscription status history, subscription invoices (link to invoices table).&lt;br /&gt;
* Notes: Acts on provider webhooks and Order events to create/update local subscription rows.&lt;br /&gt;
&lt;br /&gt;
== Payment Gateway Adapter ==&lt;br /&gt;
* Responsibility: encapsulate provider SDKs (Stripe, Paddle, etc.), create customers, payment methods, checkout sessions, subscriptions, invoices; normalize webhook payloads and verify signatures.&lt;br /&gt;
* Data owned: none (keeps provider ids for mapping).&lt;br /&gt;
* Notes: Keep this pluggable; return normalized result objects and propagate provider ids back to Order/Billing/Customer services.&lt;br /&gt;
&lt;br /&gt;
== Invoice &amp;amp; Payments Service (or module inside Billing) ==&lt;br /&gt;
&lt;br /&gt;
* Responsibility: store invoices and payments, record payment attempts, refunds, reconciliation with provider invoices, retention of raw payloads for audits.&lt;br /&gt;
* Data owned: invoices, payments, receipts.&lt;br /&gt;
* Notes: Expose APIs to query invoices and download receipts.&lt;br /&gt;
&lt;br /&gt;
== Usage / Metering Service (optional, for metered billing) ==&lt;br /&gt;
&lt;br /&gt;
* Responsibility: record per-feature usage (tokens, API calls), aggregate usage for billing periods, report usage to provider or generate usage-based invoices.&lt;br /&gt;
* Data owned: usage_records, aggregates.&lt;br /&gt;
* Notes: Support batching and idempotency (external_id) to avoid double-counting.&lt;br /&gt;
&lt;br /&gt;
[[Category:Ystack]]&lt;br /&gt;
[[Category:DDD]]&lt;br /&gt;
[[Category:Distributed]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Ystack&amp;diff=5118</id>
		<title>Ystack</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Ystack&amp;diff=5118"/>
		<updated>2025-08-17T13:41:19Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Services and responsibilities =&lt;br /&gt;
== Auth / Identity (Keycloak) ==&lt;br /&gt;
* Responsibility: Authentication, user identity, SSO, OIDC tokens.&lt;br /&gt;
* Data owned: Keycloak user record (sub), basic profile attributes.&lt;br /&gt;
* Notes: Other services store keycloak_id as foreign reference only.&lt;br /&gt;
&lt;br /&gt;
== Customer Service (customer profile / account)==&lt;br /&gt;
* Responsibility: canonical customer profile (name, emails, billing address, company, contact info), payment-customer mapping (e.g., providerCustomerId), invoice delivery preferences, links to internal user records.&lt;br /&gt;
* Data owned: customer table (customer_id, keycloak_id, contact info, provider customer id, metadata).&lt;br /&gt;
* API examples: GET/PUT customer, attach payment method token, list customer’s subscriptions/orders.&lt;br /&gt;
* When to call: read-heavy for CRM and billing, write when profile changes.&lt;br /&gt;
&lt;br /&gt;
[[Category:Ystack]]&lt;br /&gt;
[[Category:DDD]]&lt;br /&gt;
[[Category:Distributed]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Ystack&amp;diff=5117</id>
		<title>Ystack</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Ystack&amp;diff=5117"/>
		<updated>2025-08-17T13:41:08Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Services and responsibilities&lt;br /&gt;
== Auth / Identity (Keycloak) ==&lt;br /&gt;
* Responsibility: Authentication, user identity, SSO, OIDC tokens.&lt;br /&gt;
* Data owned: Keycloak user record (sub), basic profile attributes.&lt;br /&gt;
* Notes: Other services store keycloak_id as foreign reference only.&lt;br /&gt;
&lt;br /&gt;
== Customer Service (customer profile / account)==&lt;br /&gt;
* Responsibility: canonical customer profile (name, emails, billing address, company, contact info), payment-customer mapping (e.g., providerCustomerId), invoice delivery preferences, links to internal user records.&lt;br /&gt;
* Data owned: customer table (customer_id, keycloak_id, contact info, provider customer id, metadata).&lt;br /&gt;
* API examples: GET/PUT customer, attach payment method token, list customer’s subscriptions/orders.&lt;br /&gt;
* When to call: read-heavy for CRM and billing, write when profile changes.&lt;br /&gt;
&lt;br /&gt;
[[Category:Ystack]]&lt;br /&gt;
[[Category:DDD]]&lt;br /&gt;
[[Category:Distributed]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
	<entry>
		<id>https://wiki.riguz.com/index.php?title=Ystack&amp;diff=5116</id>
		<title>Ystack</title>
		<link rel="alternate" type="text/html" href="https://wiki.riguz.com/index.php?title=Ystack&amp;diff=5116"/>
		<updated>2025-08-17T13:40:53Z</updated>

		<summary type="html">&lt;p&gt;Riguz：​创建页面，内容为“ = Services and responsibilities == Auth / Identity (Keycloak) == Responsibility: Authentication, user identity, SSO, OIDC tokens. Data owned: Keycloak user record (sub), basic profile attributes. Notes: Other services store keycloak_id as foreign reference only.  == Customer Service (customer profile / account)== Responsibility: canonical customer profile (name, emails, billing address, company, contact info), payment-customer mapping (e.g., providerCustomerId…”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Services and responsibilities&lt;br /&gt;
== Auth / Identity (Keycloak) ==&lt;br /&gt;
Responsibility: Authentication, user identity, SSO, OIDC tokens.&lt;br /&gt;
Data owned: Keycloak user record (sub), basic profile attributes.&lt;br /&gt;
Notes: Other services store keycloak_id as foreign reference only.&lt;br /&gt;
&lt;br /&gt;
== Customer Service (customer profile / account)==&lt;br /&gt;
Responsibility: canonical customer profile (name, emails, billing address, company, contact info), payment-customer mapping (e.g., providerCustomerId), invoice delivery preferences, links to internal user records.&lt;br /&gt;
Data owned: customer table (customer_id, keycloak_id, contact info, provider customer id, metadata).&lt;br /&gt;
API examples: GET/PUT customer, attach payment method token, list customer’s subscriptions/orders.&lt;br /&gt;
When to call: read-heavy for CRM and billing, write when profile changes.&lt;br /&gt;
&lt;br /&gt;
[[Category:Ystack]]&lt;br /&gt;
[[Category:DDD]]&lt;br /&gt;
[[Category:Distributed]]&lt;/div&gt;</summary>
		<author><name>Riguz</name></author>
	</entry>
</feed>