In 2014, my senior and I shared a server. This server ran a Minecraft Bukkit server, two national competition projects, the university course scheduling system, the network admin recruitment system, the network admin Cyber Culture Festival homepage, an ACM online judge system, a front-end evaluation system, a dog face recognition model, a quantitative trading front-end, a Linux performance probe, a Tokyo inland flooding visualization, as well as a bunch of experimental projects.

It’s fair to say that this 1C2G server carried so many memories and witnessed my growth.

However, on one hand, I couldn’t bear to let go of this IP address, and on the other hand, the hardware and pricing in the Qingdao region could no longer meet my needs.

Rather than backing up and reinstalling the OS, it made more sense to migrate directly to a new server and pass the machine down to my juniors.

Defining the Scope of Migration

The simplest method is to run a history command to see which files were processed and which services were used before.

1
history  | grep -v cd | grep -v ls | grep -v grep | grep -v exit | grep -v history | grep -v ll | grep -v df | grep -v du | grep -v pwd | grep -v ping | grep -v wget | grep -v top | grep -v tail

It shows all the commands from when it was reset on December 4, 2016, up until now. What nostalgia~

Of course, it also made me realize that most of the projects I did before were completely meaningless…

Next, check the Nginx access logs and use ls -lrt to view them in reverse chronological order to see which domain names received traffic.

An even more tragic reality is that aside from various scanner bots, there was basically no traffic at all…

Also, don’t forget to check under the /usr/local directory.

Here, I defined the following migration scope and order:

  • Nginx configuration and SSL certificates
  • /root directory
  • /data/wwwroot directory
  • MySQL data

Installing Services

Others like Redis, Java, etc. need to be installed again:

  • MySQL
  • Nginx
  • Node
  • hexo
  • Docker
  • Dataease
  • Various dependency mirror repositories: Alibaba Cloud ACR container registry mirror, npm mirror, pip mirror, etc.
1
npm config set registry https://registry.npmmirror.com

Creating MySQL Users

First modify the root user password, then add new users.

1
2
3
4
5
6
7
8
9
10
11
12
13
grep "password" /var/log/mysqld.log
mysql -uroot -p9fr%ys1%ltKp

# 修改密码,开放外网访问权限
use mysql;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'ROOTPASSWORD';
UPDATE user SET host='%' WHERE user='root';
FLUSH PRIVILEGES;

# 新增其他用户
CREATE USER 'quant'@'%' IDENTIFIED BY 'XXX';
GRANT ALL PRIVILEGES ON quant.* TO 'quant'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;

Migrating Files

Data is priceless—back up first.

1
mysqldump -uroot -pROOTPASSWD --all-databases > DB_all_backup_20250724.sql

Using scp to copy an entire folder directly is too slow; package it into a .tar or .zip file first, then scp it over.

/data/wwwroot directory

1
2
tar -zcf wwwroot.tar.gz wwwroot/
scp wwwroot.tar.gz root@120.79.20.0:/data/

Nginx configuration files

1
2
3
4
scp /usr/local/nginx/conf/vhost/* root@120.79.20.0:/etc/nginx/conf.d
scp -r /usr/local/nginx/conf/ssl/ root@120.79.20.238:/etc/nginx
# 修改配置文件中证书指向
sed -i 's/\/usr\/local\/nginx\/conf\/ssl/\/etc\/nginx\/ssl/g' `grep ssl -rl ./`

Migrating Data

Although data migration can be done using the traditional method of importing the DB_all_backup_20250724.sql file via the source command, it is difficult to achieve a smooth incremental migration.

Therefore, I plan to use Canal to migrate MySQL.

This solution of masquerading as a slave replica was mentioned by my mentor at work back in late 2017. I finally have the chance to put it into practice.

Official documentation reference: QuickStart

OceanBase version documentation reference: Doc

Handling Upstream Dependencies

Domain Name DNS Updates

Change the A records for www, *, and @ to the new IP address. After updating, wait a bit and check whether it can be accessed normally and whether pinging the domain routes to the new IP.

GitAction Deployment Update

Since this blog is updated in real time via GitAction—automatically compiling .md files and deploying after a git push—it is necessary to set up the relevant services on the new machine.

Reference Document

For the new machine, the SSH configuration needs to be adjusted to allow login using a private key:

1
vim /etc/ssh/sshd_config
  • Change StrictModes yes to StrictModes no (uncomment and change to no)
  • Find #PubkeyAuthentication yes and change to PubkeyAuthentication yes (uncomment)
  • Find #AuthorizedKeysFile .ssh/authorized_keys and change to AuthorizedKeysFile .ssh/authorized_keys (uncomment)

Save and restart sshd:

1
systemctl restart sshd

Conclusion

The article you are reading right now already points to the new machine’s IP, and that old machine has been reset and passed on to my junior.

The first small training task for them will definitely still be deploying Minecraft in the Linux environment to play around. Looking back to when I finished deploying it and had 1v1 PKs with my senior, we completely ignored the fact that it was a sandbox game, hahaha.

Hopefully, this machine created back in ‘13 will continue to be passed down.