Skip to content

Wiki

Other Operations

About 94 min read

Existing English translations were reused. 21 current source blocks remain in Simplified Chinese, without triggering paid translation.

1.How does an industrial PC connect to Wi-Fi?

1.1.现在无法进入ssh

When we move an industrial PC from one environment to another, and we have never connected to the Wi-Fi in the new environment, how can we get the industrial PC online without a screen?

Enter the hard disk directory of the industrial PC, enter/etc/netplan/; under it there are many yamls, find the one that best matches the format below:

network: 
  version: 2 
  wifis: 
    NM-6f414fe0-2658-48ff-89ee-c7981b87bc96: 
      renderer: NetworkManager 
      match: 
        name: "wlan0" 
      dhcp4: true 
      dhcp6: true 
      access-points: 
        "EMIS_Vinci_Robocon_5G": 
          auth: 
            key-management: "psk" 
            password: "vinci666" 
          networkmanager: 
            uuid: "6f414fe0-2658-48ff-89ee-c7981b87bc96" 
            name: "EMIS_Vinci_Robocon_5G" 
            passthrough: 
              wifi-security.auth-alg: "open" 
              ipv6.addr-gen-mode: "default" 
              ipv6.ip6-privacy: "-1" 
              proxy._: "" 
      networkmanager: 
        uuid: "6f414fe0-2658-48ff-89ee-c7981b87bc96" 
        name: "EMIS_Vinci_Robocon_5G"

Change it to the new Wi-Fi name and password:

network:
  version: 2
  wifis:
    wlan0:
      dhcp4: true
      dhcp6: true
      access-points:
        "EMIS_Vinci_Robocon_5G":
          password: "vinci666"

The industrial PC can connect to the network as soon as it is powered on.

1.2.现在可以ssh

查网卡:

nmcli device status

当前连接的Wifi:

nmcli device wifi list

查询当前周围有什么wifi

sudo nmcli device wifi list --rescan yes

连接wifi:

sudo nmcli --ask device wifi connect "新的WiFi名称"

2.SSH remote development

2.1.Environment Preparation

1. Hardware Preparation

First, there must be an industrial computer (X86 small computer, professional industrial computer, Raspberry Pi, etc.).

The hardware carriers of control systems are diverse, commonly based on ARM, x86, and other architectures, such as PCs, industrial computers, Raspberry Pi, NVIDIA Jetson, etc. Different processors have their own advantages and disadvantages: PCs and industrial computers offer powerful processor performance but have high power consumption, large size, and poor flexibility, while embedded systems are the opposite. For us, we can independently select an appropriate control system based on various factors such as the robot platform's electrical requirements, load capacity, space, and purpose.

Regardless of which processor is chosen, as long as robot development is to be carried out and ROS or ROS2 is installed, then for developers, there is no essential difference in usage; or in other words, as a software engineer, in some scenarios there is no need to focus on hardware selection.

2. Set a static IP

When connecting remotely, regardless of the tool used, you need to locate the host being connected to based on its IP address, and then log in to that host using an account and password. Therefore, we need to obtain the IP address first. Moreover, since the IP is required for every connection, to ensure convenience and stability of the connection, it is best to set the IP address of the host being connected to as a static IP. The specific steps are as follows.

1. Enter the settings interface

Start the connected host (a monitor or HDMI capture card is required for startup, and after configuring SSH remote access, the monitor or HDMI capture card is no longer needed), and enter the settings interface.

2. Configure the connected network

3. Set a static IP

View the current IP address.

Set a static IP.

At this point, the IP configuration is complete.

2.2.Environment Setup

Concept

SSH (Secure Shell) is a versatile, powerful, software-based network security solution. Every time a computer sends data to the network, SSH automatically encrypts it. When the data reaches its destination, SSH automatically decrypts the encrypted data. The entire process is transparent, and using OpenSSH tools will enhance your system's security. SSH is easy to install and simple to use.

Implementation

The SSH implementation architecture is divided into two major parts: the client and the server. The client is the sender of data, and the server is the receiver of data. In the current scenario, we need to send data from the local host to the remote host. Therefore, the local host needs to install and start the SSH client, while the remote host needs to install and start the SSH server. The specific overall implementation process is as follows:

  1. Install an SSH client on the local host and an SSH server on the remote host;

  2. Start the SSH service on the remote host;

  3. Log in to the remote host from the local host;

  4. Implement data transmission.

1. Install the SSH client and server

By default, the Ubuntu system already has the SSH client installed, so you only need to install the SSH server on the remote host. The installation command is as follows:

 sudo apt install openssh-server

If the SSH client needs to be installed separately, run the following command:

sudo apt install openssh-client

2. Start the SSH service on the remote host

The command to start the SSH service on the remote host is as follows:

sudo /etc/init.d/ssh start

After startup, you can use the following command to check whether the service is running properly:

ps -e | grep ssh

If the startup is successful, the sshd program will be included.

In the future, frequent SSH remote logins will be needed. To simplify implementation, you can set the SSH service on the remote host to start automatically on boot. The command is as follows:

sudo systemctl enable ssh

3. Local remote login

To log in to the remote host, you can invoke the following command:

ssh -X 用户名@ip地址

Then, following the prompts, enter the login password to successfully log in.

To exit, you can call the exit command:

exit

4. Implement data transmission

Through SSH, on the local host, simply invoking the relevant command enables convenient data upload to or download from a remote host. The command format is as follows:

The format of the upload file instruction is as follows:

scp 本地文件路径 账号@ip:路径

The command format for uploading a folder is as follows:

scp -r 本地文件夹路径 账号@ip:路径

The download file command format is as follows:

scp 账号@ip:路径 本地文件夹路径

The format of the download folder instruction is as follows:

scp -r 账号@ip:路径 本地文件夹路径

Optimization

Every time you log in remotely, you need to enter a password, which is inconvenient. You can use keys to simplify the login process, achieve passwordless login, and improve operational efficiency. The implementation idea is: generate a pair of public and private keys, store the private key locally, and upload the public key to the server. Each time you log in, the local machine directly uploads the private key to the server. If the server has a matching public key, it considers the user legitimate and directly creates an SSH connection. The specific implementation steps are only two:

  1. Generate a key pair locally;

  2. upload the public key to the remote host.

1. Generate a key pair

Generate a public-private key pair on the local client: (press Enter for each prompt to accept the defaults)

ssh-keygen

The above command will create a public-private key pair in the .ssh folder under the user directory:

  1. id_rsa (private key);

  2. id_rsa.pub (public key).

2. Public key upload

The upload instruction is as follows:

ssh-copy-id -i ~/.ssh/id_rsa.pub 账号@ip

The above command uploads the local public key to the ssh directory on the remote host, where the file authorized_keys stores the public key content.

In the future, there will be no need to enter a password when logging in remotely.

2.3.Optimizing with VSCode

In the previous section, we introduced the use of SSH for remote connections, but using SSH alone also has some shortcomings. For example, when editing file contents, you need to use the vi editor, and within a single terminal, you cannot edit multiple files at the same time. In this section, we will introduce a more practical feature—using VSCode with plugins to achieve remote development. This allows us to perform remote development in a graphical way, making it more convenient and efficient than using SSH, and it can greatly improve programming development efficiency.

1. Preparation

VS Code remote development relies on SSH; please first configure an SSH remote connection according to the previous section.

2. Install the Remote Development extension for VSCode

Launch VSCode, first click the Extensions button in the sidebar, then in the search bar of扩展:商店enterRemote Developmentand click the plugin with the same name, and finally in the display area on the right click安装.

3. Configure remote connection

Step 1: Use the shortcut keyctrl + shift + pto open the command input window, and enterRemote-SSH:Connect to Host...; from the pop-up list, select the option with the same name.

Step 2: After Step 1 is completed, a new command window will pop up as shown below. Select from the drop-down list Add New SSH Host.

Step 3: After Step 2 is completed, a new command window will pop up. In it, enter:ssh -X ubuntu@192.168.43.164,where ubuntu needs to be replaced with your login username, and 192.18.43.164 is replaced with the IP address of the host to be remotely connected.

Step 4: Select the first option in the pop-up list after completing Step 3 (or press Enter directly) to complete the configuration. After successful configuration, a prompt message will be displayed.

4. Use

Step 1: Continue using the shortcut keyctrl + shift + pOpen the command input window and enterRemote-SSH:Connect to Host...At this point, the IP address configured in step 3 will be displayed in the list. Select it directly, and after selection, VSCode will open a new window.

Alternatively, you can click the sidebar's远程资源管理器, select the server to connect to from the pop-up server list, right-click it, and choose to establish a remote connection in the current window or a new window.

步骤2:选择菜单栏的文件下的打开文件夹,在弹窗列表中选择需要打开的文件夹并点击确定即可。

Ultimately, we can then achieve remote development just like working with local files.

2.4.Advanced

2.4.1.Use hostname for SSH

When a device's IP keeps changing, you can use the hostname to connect.

First, you can check what the hostname of the device you want to develop remotely is?

hostname

For example, the output hostnameisDell-G15-5511

Then install on this deviceavahi-daemon:

sudo apt install avahi-daemon
sudo systemctl enable --now avahi-daemon

Then you can try it on a computer on the same local network:

ping Dell-G15-5511.local

If it can be pinged successfully, that is sufficient.

Then in the future, SSH can

ssh 用户名@Dell-G15-5511.local

3.Remote Desktop

Because X11 forwarding is far too inefficient, it is still necessary to use remote desktop access to view Rviz2, Gazebo, and so on (if needed).

We choose to use VNC to view it.

  1. Install VNC server:

Here, TigerVNC is used as an example for installation:

sudo apt install tigervnc-standalone-server tigervnc-common
  1. Set VNC password:

To set a password for a VNC user, run the following command:

vncpasswd
  1. Configure the VNC startup script:

Create a VNC configuration file, and create a startup file in the .vnc folder within the user's home directory:

mkdir -p ~/.vnc
nano ~/.vnc/xstartup

Enter the following content in the opened editor (using GNOME as an example):

#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
gnome-session

Save and exit (in nano, press Ctrl + O to save, then press Ctrl + X to exit).

  1. Grant execute permission:

Set execute permissions for the xstartup file:

chmod +x ~/.vnc/xstartup
  1. Start the VNC server:
vncserver -geometry 1920x1080 -localhost=0

The geometry option specifies the window size, and the localhost option is set to 0 to open connections. (Setting it to 1 allows only local connections.)

You will see output similar to :1, which indicates the display number of the VNC session. For example, if the output is :1, the port VNC listens on is 5901 (5900 + display number).

  1. View the VNC servers that have been started:
vncserver -list

  1. Connect to the VNC server:

Use a VNC client (such as vncviewer) to connect to the VNC server and enter your server IP and port. For example, if the server IP is 192.168.31.10 and the display number is 1, you should connect to 192.168.31.10:1, or directly enter 192.168.31.10:5901.

  1. Stop the VNC server:

If you need to stop the VNC server, you can use the following command:

vncserver -kill :1

Replace :1 with the actual display number you are using.

4.Switch graphical interface

You can first look at the current default mode:

systemctl get-default

If it isgraphical.targetit is graphical mode; if it ismulti-user.targetit is command-line mode.

Turn off the graphical interface (set to command-line mode):

sudo systemctl isolate multi-user.target

Disable the graphical interface by default (boot into command-line mode by default):

sudo systemctl set-default multi-user.target

Restart

sudo reboot

5.USB device name persistence

5.1.USB port settings

In Linux, after a USB serial device is plugged in or unplugged, the device node assigned by the system may change, for example:

/dev/ttyUSB0
/dev/ttyUSB1
/dev/ttyACM0
/dev/ttyACM1

If a program, ROS node, or startup script directly hardcodes /dev/ttyUSB0, when a device is unplugged and replugged, a new USB device is added, or the system boot order changes, the port number may change.

Therefore, in scenarios such as robots, unmanned vehicles, and embedded devices, it is generally necessary to establish astable device path or fixed aliasfor USB devices.

Common approaches mainly include:

  1. Using the automatically generated by Linux /dev/serial/by-id/;
  2. Using the automatically generated by Linux /dev/serial/by-path/;
  3. According to the device's idVendor、idProduct、serial and other attributes, write udev rules;
  4. Write udev rules based on the physical location of the host USB interface;
  5. For devices such as cameras, use /dev/v4l/by-id/ or /dev/v4l/by-path/.

5.1.1.First, configure serial port permissions.

Under Linux, a regular user may not have access permission to serial devices by default, so first add the current user to the dialout user group.

#### 将当前用户加入 dialout 用户组
sudo usermod -aG dialout $USER

#### 临时在当前终端加载新的用户组
newgrp dialout

#### 查看当前用户组中是否存在 dialout
groups

If the output includes:

dialout

Indicates that the current terminal already has serial port access permission.

Alternatively, log off the current desktop session and log back in so that the user group permissions take effect throughout the entire user session.


5.2.Prioritize the use of built-in fixed device paths in Linux.

Before writing your own udev rules, it is recommended to first check whether the system has already generated a stable symbolic link for the device.

For USB serial port devices:

ls -l /dev/serial/by-id/
ls -l /dev/serial/by-path/

For example:

usb-1a86_USB_Serial-if00-port0 -> ../../ttyUSB0
usb-STMicroelectronics_STM32_Virtual_ComPort_123456-if00 -> ../../ttyACM0

Among them:

  • /dev/serial/by-id/ : mainly generated based on the device's own identity information;
  • /dev/serial/by-path/ : mainly generated based on the USB physical path through which the device is connected to the host.

5.2.1.Use /dev/serial/by-id/

If a device has a stable and unique serial number, it is usually preferred to use:

/dev/serial/by-id/xxx

For example:

/dev/serial/by-id/usb-STMicroelectronics_STM32_Virtual_ComPort_123456-if00

Even if the corresponding device node is from:

/dev/ttyACM0

becomes:

/dev/ttyACM2

by-id The path usually still remains unchanged.

Therefore, in the ROS 2 parameter, you can directly write:

port: /dev/serial/by-id/usb-STMicroelectronics_STM32_Virtual_ComPort_123456-if00

The greatest advantage of this approach is:

  • Does not depend on ttyUSBn or ttyACMn numbering;
  • After a USB device is moved to another port, it can generally still be recognized;
  • It is very stable for devices with unique serial numbers;
  • No need to write your own udev rules.

5.2.2.Use /dev/serial/by-path/

If the device does not have a unique serial number, or if the system cannot distinguish multiple identical devices through the device itself, you can use:

/dev/serial/by-path/

View:

ls -l /dev/serial/by-path/

For example:

pci-0000:00:14.0-usb-0:3:1.0-port0 -> ../../ttyUSB0
pci-0000:00:14.0-usb-0:4:1.0-port0 -> ../../ttyUSB1

This approach is actually based on:

Which USB port on the host is the device plugged into?

to distinguish devices.

For example, an autonomous vehicle has two completely identical radars:

前雷达 -> 固定插在 USB 口 A
后雷达 -> 固定插在 USB 口 B

At this point, two different by-path paths can be used directly in the program.

The disadvantages are:

If the USB ports are swapped, the corresponding logical identities of the devices will also change.


5.3.View USB device information

5.3.1.Use lsusb

After connecting a USB device, you can first execute:

lsusb

For example:

Bus 001 Device 007: ID 1a86:7523 QinHeng Electronics CH340 serial converter

Among them:

1a86:7523

Respectively correspond to:

idVendor  = 1a86
idProduct = 7523

Note:

idVendor + idProductIt can only represent a certain class of USB products and usually cannot uniquely identify a specific device.

For example, two completely identical CH340 chips:

CH340 A -> 1a86:7523
CH340 B -> 1a86:7523

Their idVendor and idProduct are completely identical.

Therefore:

  • Different device models can be distinguished by idVendor + idProduct;
  • Multiple devices of the same model cannot be distinguished solely by idVendor + idProduct.

5.3.2.View full device attributes

For serial port devices, you can use:

udevadm info --query=property --name=/dev/ttyACM0

Or:

udevadm info --query=property --name=/dev/ttyUSB0

Show only frequently used information:

udevadm info --query=property --name=/dev/ttyACM0 \
    | grep -E 'ID_(VENDOR_ID|MODEL_ID|SERIAL|SERIAL_SHORT|PATH|USB_INTERFACE_NUM)'

Common outputs:

ID_VENDOR_ID=0483
ID_MODEL_ID=5740
ID_SERIAL=STMicroelectronics_STM32_Virtual_ComPort_123456
ID_SERIAL_SHORT=123456
ID_PATH=pci-0000:00:14.0-usb-0:3:1.0
ID_USB_INTERFACE_NUM=00

Common attribute descriptions:

Attribute Meaning
ID_VENDOR_ID USB Vendor ID
ID_MODEL_ID USB Product ID
ID_SERIAL Complete device serial information
ID_SERIAL_SHORT USB device serial number
ID_PATH Physical path of the device connected to the host
ID_USB_INTERFACE_NUM USB Interface number

5.3.3.View udev matchable attributes

If you need to write your own udev rules, you can use:

udevadm info -a -p $(udevadm info -q path -n /dev/ttyACM0)

Or:

udevadm info -a -p $(udevadm info -q path -n /dev/ttyUSB0)

Alternatively, you can use:

udevadm info --attribute-walk --name=/dev/ttyUSB0

For example, view only KERNELS:

udevadm info --attribute-walk --name=/dev/ttyUSB0 | grep KERNELS

This information can be used to write custom udev rules.


5.4.Bind the port according to the USB device model

5.4.1.Requirements

In an Ubuntu system, a radar and a smart car are connected. The two devices are of different models, and fixed aliases are desired to be established for them.

For example:

雷达 -> /dev/mylidar
小车 -> /dev/mycar

5.4.2.Find idVendor and idProduct

Call:

lsusb

Assume we obtain:

雷达:10c4:ea60
小车:1a86:7523

Among them:

10c4 -> idVendor
ea60 -> idProduct

1a86 -> idVendor
7523 -> idProduct

5.4.3.Writing udev rules

At:

/etc/udev/rules.d/

Create a rule file in the directory, for example:

sudo vim /etc/udev/rules.d/99-usb-serial.rules

Input:

KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0777", SYMLINK+="mylidar"

KERNEL=="ttyUSB*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", MODE:="0777", SYMLINK+="mycar"

Among them:

  • KERNEL: Match the device name assigned by the Linux kernel;
  • ATTRS{idVendor}: USB vendor ID;
  • ATTRS{idProduct}: USB product ID;
  • MODE:="0777": Set device node permissions;
  • SYMLINK+="xxx": Create a fixed symbolic link for the device.

For example:

/dev/mylidar -> /dev/ttyUSB0
/dev/mycar   -> /dev/ttyUSB1

5.4.4.Make the rule take effect

Both Ubuntu and Fedora can uniformly use:

sudo udevadm control --reload-rules
sudo udevadm trigger

Then, unplug and reinsert the USB device.

It can also trigger only the tty subsystem:

sudo udevadm control --reload-rules
sudo udevadm trigger --subsystem-match=tty

5.4.5.Test
ls -l /dev/mylidar
ls -l /dev/mycar

Or:

readlink -f /dev/mylidar
readlink -f /dev/mycar

May obtain:

/dev/ttyUSB0
/dev/ttyUSB1

5.4.6.Disadvantages

This method is only suitable for:

Devices of different USB models.

If two devices of exactly the same model are connected:

CH340 A -> 1a86:7523
CH340 B -> 1a86:7523

Then both devices will match the same udev rule.

Therefore:

KERNEL=="ttyUSB*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="mycar"

Cannot reliably distinguish between two identical USB devices.

At this point, it is necessary to continue using:

  • USB Serial Number;
  • /dev/serial/by-id/;
  • /dev/serial/by-path/;
  • Host USB physical interface.

5.5.Bind the port based on the device Serial Number

If multiple devices are the same model but each device has a different USB serial number, then this is the most recommended custom udev binding method.

For example:

设备 A:
idVendor  = 1a86
idProduct = 55d4
serial    = 0001

设备 B:
idVendor  = 1a86
idProduct = 55d4
serial    = 0002

You can write:

KERNEL=="ttyACM*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d4", ATTRS{serial}=="0001", MODE:="0777", SYMLINK+="ttyACM_Lidar"

KERNEL=="ttyACM*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d4", ATTRS{serial}=="0002", MODE:="0777", SYMLINK+="ttyACM_MCU"

Like so:

/dev/ttyACM_Lidar
/dev/ttyACM_MCU

then it can stably correspond to two devices.

Even if:

/dev/ttyACM0
/dev/ttyACM1

the numbering is swapped, the two fixed aliases can still point to the correct devices.


5.5.1.Recommended Inspection Method
udevadm info --query=property --name=/dev/ttyACM0 | grep SERIAL

For example:

ID_SERIAL=STMicroelectronics_STM32_Virtual_ComPort_123456
ID_SERIAL_SHORT=123456

If ID_SERIAL_SHORT is unique, it is very suitable as a device identifier.


5.6.Bind ports according to the host's physical USB interfaces

5.6.1.Requirements

Two radars of exactly the same model are installed on the unmanned vehicle, one at the front and one at the rear.

Two radars:

  • idVendor same;
  • idProduct same;
  • No unique Serial Number.

At this point, it can be distinguished based on the location of the host's USB interface.


5.6.2.Method 1: Directly use /dev/serial/by-path/

First, execute:

ls -l /dev/serial/by-path/

For example:

pci-0000:00:14.0-usb-0:3:1.0-port0 -> ../../ttyUSB0
pci-0000:00:14.0-usb-0:4:1.0-port0 -> ../../ttyUSB1

It can be stipulated:

USB 口 0:3 -> 前雷达
USB 口 0:4 -> 后雷达

Program direct use:

/dev/serial/by-path/pci-0000:00:14.0-usb-0:3:1.0-port0
/dev/serial/by-path/pci-0000:00:14.0-usb-0:4:1.0-port0

即可。


5.6.3.方法二:根据 KERNELS 创建自定义别名

View the first device:

udevadm info --attribute-walk --name=/dev/ttyUSB0 | grep KERNELS

View the second device:

udevadm info --attribute-walk --name=/dev/ttyUSB1 | grep KERNELS

Assumption correspondence:

第一台:
KERNELS=="1-1.3:1.0"

第二台:
KERNELS=="1-1.4:1.0"

Then you can create:

sudo vim /etc/udev/rules.d/99-lidar.rules

Write:

KERNEL=="ttyUSB*", KERNELS=="1-1.3:1.0", MODE:="0777", SYMLINK+="rplidar_front"

KERNEL=="ttyUSB*", KERNELS=="1-1.4:1.0", MODE:="0777", SYMLINK+="rplidar_back"

Reload:

sudo udevadm control --reload-rules
sudo udevadm trigger

After re-plugging:

ls -l /dev/rplidar_front
ls -l /dev/rplidar_back

5.6.4.Disadvantages

This method binds:

Host USB interface

rather than:

The USB device itself

Therefore, the device must be plugged into a fixed USB port.

If the front and rear radars swap interfaces:

前雷达插到后雷达 USB 口

Then the system will still identify the interface as:

/dev/rplidar_back

5.7.According to ID_PATH bind port

Similar to using KERNELS, rules can also be established based on ID_PATH.

View:

udevadm info --query=property --name=/dev/ttyUSB0 | grep ID_PATH

For example:

ID_PATH=pci-0000:00:14.0-usb-0:3:1.0

You can write:

SUBSYSTEM=="tty", ENV{ID_PATH}=="pci-0000:00:14.0-usb-0:3:1.0", MODE:="0777", SYMLINK+="rplidar_front"

Another interface:

SUBSYSTEM=="tty", ENV{ID_PATH}=="pci-0000:00:14.0-usb-0:4:1.0", MODE:="0777", SYMLINK+="rplidar_back"

Compared with writing KERNELS directly, this approach is usually more intuitive.


5.8.Composite multiple attribute binding ports

In practical engineering, multiple attributes can be matched simultaneously.

For example:

KERNEL=="ttyACM*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d4", ATTRS{serial}=="0001", MODE:="0777", SYMLINK+="ttyACM_Lidar"

KERNEL=="ttyACM*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d4", ATTRS{serial}=="0002", MODE:="0777", SYMLINK+="ttyACM_MCU"

KERNEL=="ttyUSB*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", MODE:="0777", SYMLINK+="ttyUSB_IMU"

Alternatively, you can use:

SUBSYSTEM=="tty", ENV{ID_VENDOR_ID}=="0483", ENV{ID_MODEL_ID}=="5740", ENV{ID_SERIAL_SHORT}=="12345678", MODE:="0777", SYMLINK+="ysu_mcu"

Finally, we get:

/dev/ysu_mcu

This approach is very suitable for robotics projects.


5.9.It is recommended to use a unified business device name

For robotics projects, it is not recommended that ROS 2 nodes be used directly:

/dev/ttyUSB0
/dev/ttyACM0

Business names can be established uniformly, for example:

/dev/ysu_mcu
/dev/ysu_gimbal
/dev/ysu_imu
/dev/ysu_lidar_front
/dev/ysu_lidar_back

For example:

SUBSYSTEM=="tty", ENV{ID_VENDOR_ID}=="0483", ENV{ID_MODEL_ID}=="5740", ENV{ID_SERIAL_SHORT}=="12345678", MODE:="0777", SYMLINK+="ysu_mcu"

SUBSYSTEM=="tty", ENV{ID_VENDOR_ID}=="10c4", ENV{ID_MODEL_ID}=="ea60", ENV{ID_SERIAL_SHORT}=="ABCDEF", MODE:="0777", SYMLINK+="ysu_imu"

SUBSYSTEM=="tty", ENV{ID_PATH}=="pci-0000:00:14.0-usb-0:3:1.0", MODE:="0777", SYMLINK+="ysu_lidar_front"

Then ROS 2 parameters write:

serial_port: /dev/ysu_mcu
imu_port: /dev/ysu_imu
lidar_port: /dev/ysu_lidar_front

This way, when the device node number is subsequently changed, ROS 2 the configuration file does not need to be modified at all.


5.10.ttyUSB difference between ttyACM and

Not all USB serial devices use:

/dev/ttyUSBn

Common types are as follows:

Device Type Kernel Name Example Description
USB-to-Serial Chip ttyUSB* CH340, CP210x, FTDI, etc.
USB CDC ACM ttyACM* STM32 CDC, Arduino, etc.
Host Physical Serial Port ttyS* PC onboard UART
USB Camera video* V4L2 Camera
Disk sd* USB hard drive, USB flash drive
Input Device event* Keyboard, mouse, gamepad
Bluetooth Serial Port rfcomm* Bluetooth RFCOMM

So in the udev rule:

KERNEL=="ttyUSB*"

It is not a fixed notation.

If the STM32 CDC corresponds to:

/dev/ttyACM0

Then it should match:

KERNEL=="ttyACM*"

It can also be used uniformly:

SUBSYSTEM=="tty"

Then filter in combination with other attributes.


5.11.USB camera fixed device path

A USB camera typically corresponds to:

/dev/video0
/dev/video1
/dev/video2
...

Moreover, a single camera can sometimes generate multiple /dev/videoN nodes.

Therefore, it is not advisable to simply assume:

video0、video2、video4 一定是摄像头采集节点

This is because the device node numbering and interface order may change.


5.11.1.View the camera fixed path generated by the system

Execute:

ls -l /dev/v4l/by-id/
ls -l /dev/v4l/by-path/

For example:

/dev/v4l/by-id/usb-USB_Camera-video-index0
/dev/v4l/by-id/usb-USB_Camera-video-index1

If the camera has unique identity information, it is recommended to use:

/dev/v4l/by-id/

If differentiation is required based on a fixed USB interface:

/dev/v4l/by-path/

5.11.2.View camera node

Can install:

sudo apt install v4l-utils

Then:

v4l2-ctl --list-devices

For example:

USB Camera:
    /dev/video0
    /dev/video1

You can also further view the formats supported by a particular node:

v4l2-ctl -d /dev/video0 --all

5.12.Fixed path of the disk device

For USB hard drives, USB flash drives, SSDs, etc., it is not recommended to rely directly on:

/dev/sda
/dev/sdb

Linux also provides:

/dev/disk/by-id/
/dev/disk/by-path/
/dev/disk/by-uuid/
/dev/disk/by-label/

For example:

ls -l /dev/disk/by-id/

Therefore, different types of devices all follow similar principles:

动态设备节点
        ↓
系统生成固定路径
        ↓
必要时自己编写 udev rule

5.13.Activate udev rules

Modify:

/etc/udev/rules.d/*.rules

Afterward, both Ubuntu and Fedora can use:

sudo udevadm control --reload-rules
sudo udevadm trigger

Then reinsert the device.

For serial port devices, you can also:

sudo udevadm trigger --subsystem-match=tty

If the rule still does not take effect, you can directly restart the system.


5.14.Test fixed alias

View symbolic link:

ls -l /dev/ysu_mcu

View the final actual device:

readlink -f /dev/ysu_mcu

For example:

/dev/ttyACM1

Even if reinserting the device afterwards becomes:

/dev/ttyACM3

If the udev rule matches correctly:

/dev/ysu_mcu

it will still point to the correct device.


5.15.Troubleshoot udev rules

If the rule has not taken effect, you can check it by following the methods below.


5.15.1.Check rule syntax
sudo udevadm verify /etc/udev/rules.d/99-usb-serial.rules

If the current system version supports this command, the rule file can be checked directly.


5.15.2.View device properties
udevadm info --query=property --name=/dev/ttyUSB0

Or:

udevadm info --attribute-walk --name=/dev/ttyUSB0

Key checks:

idVendor
idProduct
serial
ID_SERIAL
ID_SERIAL_SHORT
ID_PATH
KERNELS
SUBSYSTEM

5.15.3.Monitoring device plug and unplug events

Execute:

udevadm monitor --environment --udev

Then, unplug and reinsert the USB device.

You can observe the udev attributes generated when the system recognizes the device.


5.15.4.View the device's actual permissions
ls -l /dev/ttyUSB0

For example:

crwxrwxrwx 1 root dialout ...

If used in rules:

MODE:="0777"

After the device is regenerated, permissions will be set according to the rules.


5.16.Recommended selection order

When fixing a USB device to a port, it is recommended to select in the following order.

                USB设备
                   │
                   ▼
       是否已有系统固定路径?
         /dev/serial/by-id
                   │
             ┌─────┴─────┐
             │           │
            有           无
             │           │
             ▼           ▼
          直接使用     是否存在唯一Serial?
                         │
                   ┌─────┴─────┐
                   │           │
                  有           无
                   │           │
                   ▼           ▼
             按Serial绑定   是否固定USB接口?
                               │
                         ┌─────┴─────┐
                         │           │
                        是           否
                         │           │
                         ▼           ▼
                    by-path/      尽量从设备固件
                    ID_PATH       层增加唯一Serial

In simple terms:

If the device itself can be identified, bind by the device itself; if the device itself cannot be identified, bind by the USB port to which the device is connected.


5.17.Final Recommended Solution

5.17.1.Case 1: A single device with a unique Serial

Preferred:

/dev/serial/by-id/

Or create your own:

/dev/ysu_mcu

5.17.2.Case 2: Multiple devices of different models

Can be used:

idVendor + idProduct

Create a custom udev rule.


5.17.3.Case 3: Multiple identical devices but with different serial numbers

Usage:

idVendor + idProduct + serial

This is a very stable solution.


5.17.4.Case 4: Multiple identical devices with no unique Serial

Usage:

/dev/serial/by-path/

Or:

KERNELS
ID_PATH

Distinguish based on the host's USB physical interface.


5.17.5.Case 5: STM32 Custom USB CDC

If the device firmware is under your own control, it is recommended to configure a unique Serial Number in the USB Descriptor.

This allows Linux to create a stable path based on the device's own identity, for example:

/dev/serial/by-id/usb-STMicroelectronics_STM32_Virtual_ComPort_xxxxx-if00

After that, no matter which USB port it is plugged into, the same control board can be recognized.


5.18.Summary

The persistent naming of Linux USB devices can essentially be divided into two categories:

根据设备是谁
    ↓
by-id
Serial Number
idVendor + idProduct + serial


根据设备插在哪里
    ↓
by-path
ID_PATH
KERNELS

Recommended priority in engineering:

/dev/serial/by-id/
        ↓
唯一 Serial Number
        ↓
/dev/serial/by-path/
        ↓
自定义 udev rules

In robotics projects, the following can ultimately be established in a unified manner:

/dev/ysu_mcu
/dev/ysu_gimbal
/dev/ysu_imu
/dev/ysu_lidar_front
/dev/ysu_lidar_back

Afterwards, ROS 2, C++ programs and startup files all use these fixed names and no longer rely on:

/dev/ttyUSB0
/dev/ttyUSB1
/dev/ttyACM0
/dev/ttyACM1

This way, even if the USB device is unplugged and reinserted, the boot order changes, or the system reallocates port numbers, the upper-layer program will not be affected.

6.Linux Partition GUI Tool

sudo apt install gparted
sudo dnf install gparted

7.DDNS

8.Mount intranet webpage

You can mount the local web page on the router side, or on other devices in the same intranet segment, and even mount it locally.

The following uses an Android device as an example. Since Android devices currently cannot directly open HTML, we can host the HTML on a local server and then view it through a browser.

Since the Android system is based on the Linux kernel, we can download an app called Termux to type some Linux commands:

https://github.com/termux/termux-app

First, after opening the app, update the software cache:

pkg update

Then switch the source

nano $PREFIX/etc/apt/sources.list

Replace the file content with the following:

deb https://mirrors.bfsu.edu.cn/termux/termux-packages-24 stable main
  • If you are using thenanoeditor:

    • Press Ctrl+O to save the file.

    • Press Enter to confirm the filename.

    • Press Ctrl+X to exit the editor.

  • If you are using thevimeditor:

    • Press Esc to exit edit mode.

    • Type :wq to save and exit.

Next, update the software sources again:

pkg update && pkg upgrade

Install Python:

pkg install python3

Access device storage via Termux :

If the file is on an Android device, you can use Termux's file manager to access the device's storage:

termux-setup-storage
  1. Navigate to the directory containing the HTML file :

    1. Use thecdcommand to navigate to the directory where the HTML file is located:
cd ~/your_html_folder
  1. Start a Python HTTP server :

    1. Run the following command to start a simple HTTP server:
    python3 -m http.server 8000
    1. This will start a web server on port8000.
  • After starting the server, Termux will display log information, for example:
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
  • This indicates that the server has started successfully.

Access HTML files in the browser

  1. Access on the same device :

    1. Open a browser on the Android device (e.g., Chrome) and enter the following address:
    http://localhost:8000
    1. If the HTML file containsindex.htmlit will load automatically; otherwise, you need to manually click the file link.

9.RustDesk

9.1.RustDesk Unattended Remote Control

目前rustdesk还没办法进行无人值守在wayland下,所以我们需要把登陆密码,锁屏和休眠待机全部关掉.

9.1.1.Set up KDE6 automatic login
  1. You can first check your own SDDM type.
ls /usr/share/xsessions/
ls /usr/share/wayland-sessions/

See which one outputs content; the folder that outputs content is the sddm you have. For example, if xsessions outputs content, then it is the X11 sddm; if wayland-sessions outputs content, then you have the Wayland sddm.

  1. Edit the SDDM configuration:
sudo nano /etc/sddm.conf

在文件最上面有个[Autologin],在这个底下加入下面的内容:

[Autologin]
User=你的用户名
Session=plasma.desktop   # 或 plasma.desktop(X11),方案一可用 Wayland
  1. After saving and exiting, restart SDDM:
sudo systemctl restart sddm

✅ Automatically enter the desktop after startup without entering a password

9.1.2.Disable the lock screen in KDE6 system settings:

Open System Settings → Screen Locking. Disable Automatic Locking. Disable Screen Off / Screen Saver Locking. This way, RustDesk can directly control the desktop after boot without being blocked by the lock screen.

9.1.3.Turn off hibernation System Settings → Power Management

Disable "Sleep" or "Automatic Suspend" Keep the computer powered on and online so RustDesk can provide remote control at any time If sleep is necessary, you can disable sleep in the BIOS settings to ensure it connects to the network upon startup

9.2.RustDesk self-hosted server

9.2.1.Install on the server side
9.2.1.1.Command-line mode
  1. Open the official website:https://rustdesk.com/docs/zh-cn/self-host/

alt text

  1. To access via SSH, you need to install RustDesk on the server.
ssh tungchiahui@10.0.0.4

alt text

  1. Use the command in Method 2

alt text

wget https://raw.githubusercontent.com/techahold/rustdeskinstall/master/install.sh
chmod +x install.sh
./install.sh

See the next section for the settings of ./install.sh

  1. Configure and View KEY

Here, if you want to directly use the public IP, select1)IP, and if you use DDNS or a domain name bound to an IP address, select2).

alt text

Select this2)No

alt text

This is the KEY. Copy it down, as it will be needed later during software configuration.

alt text

  1. Configure the firewall

    1. If you are using a Debian-based system Install the firewall
    sudo apt install ufw

    Configure the firewall

    sudo ufw allow 22
    
    ufw allow 21114:21119/tcp
    ufw allow 21116/udp
    sudo ufw enable
    1. If you are using a RHEL-based system Install the firewall
    # 如果你是RHEL系
    sudo dnf install firewalld
    sudo systemctl enable --now firewalld

    Configure the firewall

    sudo firewall-cmd --add-port=22/tcp --permanent
    sudo firewall-cmd --reload
    
    sudo firewall-cmd --add-port=21114-21119/tcp --permanent
    sudo firewall-cmd --reload
    
    sudo firewall-cmd --add-port=21116/udp --permanent
    sudo firewall-cmd --reload
    
    sudo systemctl enable --now firewalld
9.2.1.2.1Panel method
  1. Search for RustDesk in the panel and install it

alt text

  1. Configure the firewall

alt text

Add a few ports alt text alt text alt text

  1. View KEY alt text

Copy KEY

alt text

9.2.2.Configuring RustDesk software after self-hosting the server
  1. PC side

alt text

alt text

If "ready" appears, the configuration is successful alt text

  1. Mobile

alt text

alt text

9.2.2.1.Issues to Note

If it is an internal network server for the home, you also need to allow the corresponding port on the router.

Find the OpenWrt firewall settings, click Add alt text

alt text

alt text

Then you also need to allow IPv6. Debian generally leaves IPv6 unfiltered by default, but it will be blocked by the upstream OpenWrt, so you need to enable the corresponding rules in OpenWrt.

Go to|"防火墙 - 通信规则" and add the following two configurations.

Allow-RustDesk-IPv6-TCP
WAN → LAN
目标:你服务器的ipv6公网
TCP 21115-21119
动作:接受转发

Allow-RustDesk-IPv6-UDP
WAN → LAN
目标:你服务器的ipv6公网
UDP 21116
动作:接受转发

Only in this way can your server port truly be successfully allowed through.

10.WireGuard

10.1.Introduction

WireGuard is a tool used to access intranet devices outdoors through a VPN.

Here my tutorial will teach you how to access your home's intranet devices from outside.

10.2.My Environment

10.2.1.Intranet

Home LAN subnet:10.0.0.0/24

alt text

10.2.2.External device

If you are connecting to the office Wi-Fi in a place such as an office, then you need to know室外内网网段, if you are directly using mobile data, then you do not need to know anything.

Outdoor intranet subnet:192.168.31.0/24 Outdoor data traffic operator: China Unicom

10.3.Install

10.3.1.Server side - soft router side

Log in to OpenWrt via SSH, or use the LuCI interface:

opkg update
opkg install wireguard-tools luci-proto-wireguard kmod-wireguard qrencode

After installation, refresh the browser LuCI page.

10.3.2.Client - Mobile, Desktop

https://www.wireguard.com/install/

  1. Android

https://play.google.com/store/apps/details?id=com.wireguard.android&hl=zh&pli=1

  1. iOS

US region:https://apps.apple.com/us/app/wireguard/id1441195209 Japan region:https://apps.apple.com/jp/app/wireguard/id1441195209 Taiwan region:https://apps.apple.com/tw/app/wireguard/id1441195209

  1. Linux

    1. Fedora
     sudo dnf install wireguard-tools
    
    1. Ubuntu/Debian
sudo apt install wireguard

10.4.Configuration

10.4.1.Server side - Initialization configuration

In the LuCI interface, click网络 → 接口 → 添加新接口

  1. For the protocol, select WireGuard VPN
  2. For the name, enter wg0
  3. Click Next to go to the details page

alt text

Configure in sequence according to the steps in the image above. Let me explain here. Listening port:51820(Customizable; just use an unused port. Remember this port. If you don't understand, just follow my settings.) IP address:10.10.10.1/24(VPN internal network segment; it must not conflict with your soft router's LAN segment. If you don't understand, just follow my settings.)

You must ensure that your家庭内网网段and your室外内网网段as well as the IP address just filled in, cannot belong to the same subnet.

For example, my家庭内网网段is10.0.0.0/24, while室外内网网段is192.168.31.0/24, and the VPN subnet10.10.10.0/24.

Then click firewall settings and selectWireGuard.

alt text

10.4.2.Server-side peer configuration

这里配置的就是你的手机/笔记本作为客户端连进来的信息:

这个界面很方便,LuCI可以直接帮你生成客户端的密钥对并直接导出配置文件/二维码,不需要你手动在手机上先生成公钥再倒腾过来,效率高很多。按下面顺序填:

  1. 描述 phone (或者你自己好记的名字,比如"iPhone17")
  2. 公钥 + 私钥 —— 直接点"生成新的密钥对" 点这个按钮,系统会自动帮你同时生成一对新的公钥+私钥,并自动填到"公钥"和"私钥"两个框里。 这个做法比你自己在手机App里生成再抄公钥过来省事得多,因为最后可以直接导出完整配置文件甚至二维码给手机扫码导入,私钥也是配置好的,不用手动输入。
  3. 预共享密钥(PSK) —— 建议点"生成预共享密钥" 这是可选的额外加密层,加上更安全(抗未来量子计算破解),点一下"生成预共享密钥"按钮自动填好即可,不需要手动操作。
  4. 允许的IP 点绿色+号,填: 10.10.10.2/32 这是分配给这台手机的隧道内网IP(如果以后要加第二台设备,比如笔记本,就用10.10.10.3/32,以此类推)。
  5. 为允许的IP创建路由 —— 勾选 这个决定了服务端要不要给这个IP自动建路由,勾上,否则服务端不知道怎么把去往10.10.10.2的包转发给这个peer。
  6. 对端地址 (Image 2) 这个字段填的是客户端的地址,但因为你的手机是移动设备、IP会变,服务端这边留空即可,不用填。(这个字段一般是给"两个固定IP的服务器互联"场景用的,你这种手机/笔记本客户端场景不需要)
  7. 对端端口 同理,留空或者保持默认51820占位符不用管,服务端这边这个字段对客户端场景没意义,跳过。
  8. 持续保持连接(Persistent Keepalive) 填: 25 因为手机大概率处在NAT环境下(无论是WiFi还是4G/5G),这个值能防止连接因为长时间无流量被NAT设备判定断开。
  9. 保存后 —— 点"生成配置..." 这一步是重点:全部填完先点右下角"保存",保存完之后再进来点 配置导出 那个"生成配置..."按钮,系统会:

Automatically generate a complete client configuration file (including all information such as the private key, server public key, Endpoint address, etc.) A QR code is usually also displayed.

The WireGuard app on your phone can scan this QR code to import the configuration in one step, without you having to manually enter any fields—it is the most hassle-free option.

  1. 填完这些保存之后,点"生成配置"

    alt text

    1. 连接端点 —— 改成DDNS域名 没有ddns域名的请看ddns教程. 现在显示的是 112.233.39.5 这个具体的公网IPv4,这是系统自动探测到的当前公网IP,但建议改成:ddns.xxxxxx.cn 原因很简单:家庭宽带的公网IP大概率是动态的(如果你是中国移动,你完全不需要担心这件事情,你没有公网ipv4,你只有公网ipv6),过一阵子运营商重新分配IP后,这个写死的IP就失效了,配置文件也就废了。用DDNS域名的话,只要你路由器上的DDNS客户端正常更新,域名自动跟着IP变化解析,配置文件永久有效,不用来回改。 直接把这个下拉框里的值改成 ddns.tungchiahui.cn 即可,如果下拉框里没有这个选项,看能不能手动输入替换。
    2. 允许的IP —— 这个要看你的使用需求,建议改 现在是 0.0.0.0/0 + ::/0,意思是全局代理模式:连上VPN后,手机/电脑的所有上网流量(刷网页、看视频、聊天全部)都会先绕道回你家里,再从家里的网络出去上网。 这跟最初的需求("在外面访问家里NAS")不太一致,全局模式的影响:

    ✅ 优点:所有流量都通过加密隧道,公共WiFi环境下更安全 ❌ 缺点:手机所有网络流量的速度都取决于你家宽带的上传带宽,如果你家是常见的百兆宽带(上传可能才几十M甚至更低),刷视频、下载会明显变慢;而且家里NAT要承担所有流量的转发压力

    如果你只是想访问家里内网的NAS/PVE/Debian,建议改成分离隧道模式,把这两行改成: 10.10.10.0/24 10.0.0.0/24 删掉 0.0.0.0/0 和 ::/0 这两行(点它们右边的红色×号),只保留上面这两个网段。这样只有"访问家里内网"这一类流量才走VPN隧道,其他正常上网流量不受影响,速度不受影响。 如果你确实希望VPN也当"全局代理"用(比如出门用境外的WiFi想用家里的网络环境访问某些内容),那就保留 0.0.0.0/0 不用改。

    1. DNS服务器:10.0.0.1 —— 这是你家庭内网的软路由的LAN地址,连VPN后用它解析域名没问题,能顺带解析你家内网可能配置的一些本地域名
    2. 地址:10.10.10.2/32 —— 这个就是你想给你的这个手机分配一个VPN网段

alt text

Then take out the mobile client and import the configuration using the QR code.

alt text

10.4.3.Server - Firewall Settings

Rules to add Go to Network → Firewall → Traffic Rules, and click "Add":

alt text

Name: WireGuard (name it whatever you like) Protocol: UDP or TCP/UDP Source zone: wan Destination zone: Device (Input) — because WireGuard listens on a port on the soft router itself, rather than forwarding to other devices on the LAN Destination port: 51820 (the same as the "Listen Port" you entered for the wg0 interface) Action: Accept

alt text

Save and apply.

10.4.4.Client

Take iOS as an example.

Here I use mobile data for testing, using China Unicom 4G.

Just open the configuration you imported as you would use a normal VPN.

alt text

10.5.test

Then you can try to access your intranet devices, for example, my openwrt is 10.0.0.1, pve is 10.0.0.2, nas is 10.0.0.5, and all can be accessed normally.

alt text

alt text

alt text

10.6.Hand over WireGuard to Clash Meta for management (optional)

10.6.1.Put a pure WireGuard configuration into Clash Meta

If a client that supports the Mihomo / Clash Meta core has already been running on a phone or computer for a long time, starting a separate WireGuard client would be rather troublesome, and the same mobile device usually cannot enable two VPN tunnels at the same time.

Therefore, WireGuard nodes can be written directly into the Clash Meta configuration, letting Clash Meta uniformly handle:

  1. Direct connection for regular internet traffic;
  2. Home intranet traffic is accessed through WireGuard;
  3. Automatically determine which exit the traffic should take based on rules.

This section only describes pure WireGuard configurations that do not include airports or other proxy nodes.

After configuration is complete, you no longer need to open a separate WireGuard client. When using this configuration, you should turn off the tunnel in the WireGuard App and only open Clash Meta.

10.6.1.1.View WireGuard client parameters

First, open a WireGuard client configuration that is already working properly, and record the following information:

Clash Meta field Corresponding field in WireGuard client
server Endpoint domain or public IP in Peer
port Endpoint port in Peer
ip Addresses in Interface, fill in only IPv4 address, do not write/32
private-key Private key in Interface
public-key Public key in Peer, that is, the WireGuard server public key
pre-shared-key Preshared key in Peer
persistent-keepalive Persistent keepalive in Peer

The most easily confused thing here is the two public keys:

  • The Public key in the Interface is the current client's public key and cannot be filled into Clash Meta'spublic-key;
  • The Public key in the Peer is the WireGuard server's public key and needs to be filled into Clash Meta'spublic-key.

WireGuard客户端参数位置

This single figure contains both the Interface and Peer parts, which is already sufficient to explain where each field should be obtained from; no additional screenshots are needed.

10.6.1.2.Create YAML configuration

Create a new file with the extension.yaml,for example:

home-wireguard.yaml

Write into the following template:

# 仅让家庭内网流量通过WireGuard
# 普通互联网流量保持直连
# 启用本配置时,不要同时开启独立的WireGuard客户端

mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
ipv6: true

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true

proxies:
  - name: 家庭-WG
    type: wireguard

    # WireGuard客户端Peer中的Endpoint
    server: ddns.example.com
    port: 51820

    # WireGuard客户端Interface中的Addresses
    # 例如原配置为10.10.10.2/32,这里只填写10.10.10.2
    ip: 10.10.10.2

    # WireGuard客户端Interface中的Private key
    private-key: "gBzeTbZH..."

    # WireGuard客户端Peer中的Public key,即服务器公钥
    # 不要填写Interface中的客户端公钥
    public-key: "UUS0nrKE..."

    # WireGuard客户端Peer中的Preshared key
    pre-shared-key: "NGYvFsCle..."

    allowed-ips:
      - 0.0.0.0/0

    udp: true
    persistent-keepalive: 25
    mtu: 1380

rules:
  # 家庭局域网网段
  - IP-CIDR,10.0.0.0/24,家庭-WG,no-resolve

  # WireGuard隧道网段
  - IP-CIDR,10.10.10.0/24,家庭-WG,no-resolve

  # 其他网络流量保持直连
  - MATCH,DIRECT
10.6.1.3.Modify the parameters in the template.

You need to modify the following content according to your own WireGuard configuration.

1. server

Will:

server: ddns.example.com

Change it to the domain name or public IP before the colon in the Endpoint of the WireGuard client Peer.

For example, the Endpoint is:

ddns.example.com:51820

Then fill in:

server: ddns.example.com

2. port

Fill in the port after the colon in the Endpoint, for example:

port: 51820

3. ip

Enter the Addresses in the WireGuard client Interface, but do not enter the CIDR suffix.

For example, the original configuration is:

10.10.10.2/32

Fill in Clash Meta:

ip: 10.10.10.2

4. private-key

Enter the Private key in the WireGuard client Interface:

private-key: "客户端私钥"

5. public-key

Fill in the Public key in the WireGuard client Peer, that is, the server public key:

public-key: "服务器公钥"

Do not mistakenly fill in the Public key in the Interface. The Public key in the Interface belongs to the current client, while the Public key in the Peer belongs to the server.

6. pre-shared-key

Enter the Preshared key in the WireGuard client Peer:

pre-shared-key: "预共享密钥"

A WireGuard key is a Base64 string; when copying it, do not miss the possible trailing=.

7. rules

Change the home LAN subnet and WireGuard tunnel subnet in the rules to your actual subnets.

For example:

rules:
  - IP-CIDR,10.0.0.0/24,家庭-WG,no-resolve
  - IP-CIDR,10.10.10.0/24,家庭-WG,no-resolve
  - MATCH,DIRECT

Indicates:

  • Access10.0.0.0/24When accessing the home LAN, use WireGuard;
  • Access10.10.10.0/24When accessing the WireGuard tunnel subnet, use WireGuard;
  • All other traffic is directly connected and does not go through the home broadband.
10.6.1.4.About allowed-ips

In the template:

allowed-ips:
  - 0.0.0.0/0

It can remain unchanged.

它表示这个WireGuard代理节点能够承载全部IPv4流量,但实际哪些流量交给WireGuard,仍然由最下面的rules决定。

For example:

rules:
  - IP-CIDR,10.0.0.0/24,家庭-WG,no-resolve
  - IP-CIDR,10.10.10.0/24,家庭-WG,no-resolve
  - MATCH,DIRECT

Under this set of rules, only the home intranet and the WireGuard tunnel subnet go through WireGuard, while other internet traffic continues to connect directly.

Note that the Allowed IPs in the WireGuard server-side Peer should still be the address assigned to that client, for example:

10.10.10.2/32

Do not change the Allowed IPs in the WireGuard server Peer to0.0.0.0/0.

10.6.1.5.Import and test

Import the YAML file into a client that supports the Mihomo / Clash Meta core, then:

  1. Disable the standalone WireGuard client tunnel;
  2. Select the configuration just imported in Clash Meta;
  3. Use "Rule" mode;
  4. Turn on the Clash Meta connection switch;
  5. Access home intranet devices for testing.

For example, accessing a soft router:

http://10.0.0.1

Or connect to a NAS in the iOS Files app:

smb://10.0.0.5

At the same time, you can access the WireGuard server to view the Latest Handshake of the corresponding peer.

If the handshake time refreshes after enabling Clash Meta and home intranet devices can be accessed, it means the configuration is successful.

10.6.1.6.FAQ

If YAML can start but fails to produce a WireGuard handshake, prioritize checking:

  1. public-keyWhether it was mistakenly filled in as the client public key;
  2. private-keyWhether it is the current client private key;
  3. pre-shared-keyWhether it is complete, and whether the trailing=is omitted;
  4. ipWhether it is consistent with the address assigned to this peer by the server;
  5. Whether the Endpoint domain name and port are correct;
  6. Whether the soft router firewall has already allowed the WireGuard port;
  7. Whether the standalone WireGuard client is still enabled.

If the error is similar to:

decode pre shared key: illegal base64 data

General descriptionpre-shared-keyThe copy is incomplete. A common cause is that the=at the end was omitted.

10.6.2.Add WireGuard to the YAML containing proxy nodes

11.Alist

11.1.Introduction

11.2.Install

11.3.WebUI

11.4.S3 protocol

11.4.1.Enable S3

First, enable the S3 protocol.

Go to/opt/1panel/apps/alist/alist/data/dataModify the settings in the directory as shown in the figure, changing fromfalsetotrue.

"s3": {
  "enable": true,
  "port": 5246,
  "ssl": false
}

Finally, click restart.

11.4.2.Test S3 link

Type it on the deployed AList server itself

curl -i http://127.0.0.1:5246/

If it showsHTTP/1.1 200 OK then it proves it is OK.

Later, I also reverse-proxied it to a domain names3.tungchiahui.cn and after testing, there were no issues either:

11.4.3.Configure S3

In the AList management interface, find S3 in the settings, then click Add at the bottom to add which path as a bucket:

  • Name is the name of the bucket
  • Path is the path you want AList to use as the root directory of the bucket
  • S3 access key id is the S3 authorization ID
  • S3 secret access key is the S3 authorization key

11.4.4.Test S3

First, prepare your configuration.

Endpoint:
http://127.0.0.1:5246
或者
https://s3.tungchiahui.cn

Bucket:
ObjectStorage

Access Key:
AList 后台生成的 S3 Access Key ID

Secret Key:
AList 后台生成的 S3 Secret Access Key

Region:
us-east-1

Use software that can use S3, for example, I use the VScode plugin I made for testing.

The plugin link is as follows: https://marketplace.visualstudio.com/items?itemName=tungchiahui.md-image-uploader

I filled the configuration into VSCode'ssettings.jsonTested using my plugin:

{
  "mdImageUploader.s3.accessKeyId": "2Vxxxxxxxxxxxxxxxxxxxxxx",
  "mdImageUploader.s3.secretAccessKey": "FWx6xxxxxxxxxxxxxxxxxx",
  "mdImageUploader.s3.endpoint": "https://s3.tungchiahui.cn",
  "mdImageUploader.s3.region": "us-east-1",
  "mdImageUploader.s3.bucket": "ObjectStorage",
  "mdImageUploader.cdnUrl": "https://cdn.tungchiahui.cn",
  "mdImageUploader.datedUploadPath": "/tungwebsite/assets/images",
  "mdImageUploader.undatedUploadPath": "/tungwebsite/assets/images/undate"
}

After testing, the file has been successfully saved to the bucket.

11.4.5.Create file direct link

Go to AList backend

管理
→ 设置
→ 全局
→ 关闭Sign All

If Sign All is on, turn it off. Because as long as the global Sign All is on, individually storing signatures off below is useless. AList officially states that Sign All adds signatures to all file direct links.

Then find the storage location of the bucket where your AList is stored and edit it.

Close启用签名 / Enable signing.

Then save.

Then you can access the file through![](https://alist.tungchiahui.cn/d/AList文件的路径/文件名.webp).

Advanced operations (optional):

Setcdn.tungchiahui.cnalso andalist.tungchiahui.cnsame-origin, then accelerate in Tencent Cloud EdgeOne, and add a new rule forcdn路径前缀增加in the rules engine.

  • Host selectioncdn.tungchiahui.cn
  • Operation selection回源URL重写
  • Type selection增加路径前缀
  • Add path prefix selection/d/AList文件的多余路径/

For example增加路径前缀what I filled in/d/NAS/ObjectStorage, Then I usehttps://cdn.tungchiahui.cn/tungwebsite/assets/images/2024/03/30/1787159371048-e2e3749f.webp will be equivalent tohttps://alist.tungchiahui.cn/d/NAS/ObjectStorage/tungwebsite/assets/images/2024/03/30/1787159371048-e2e3749f.webp, all will be back-to-origin to myhttps://服务器ip地址/d/NAS/ObjectStorage/tungwebsite/assets/images/2024/03/30/1787159371048-e2e3749f.webp.

Set another caching rule:

Cache rules can be understood as follows:

  • Node cache TTL: 30 days
    EdgeOne will cache images on edge nodes for 30 days. Subsequent access will preferentially be returned from CDN nodes, which can significantly reduce the pressure on AList, the server, and server bandwidth.

  • Force cache: Off
    Keeping it off is safer. If the origin server explicitly requires that certain resources not be cached, EdgeOne will respect the origin server settings and avoid incorrectly caching special resources.

  • Cache Key: Ignore all query strings
    For example:

    xxx.webp
    xxx.webp?a=1
    xxx.webp?a=2
    xxx.webp?a=3

    will all be considered the same cached resource. This can prevent others from continuously modifying URL parameters to bypass the cache and repeatedly hitting your AList and server, and since my files are also stored on a NAS, it will further prevent them from repeatedly hitting my NAS.

  • Ignore case: Off
    abc.webp and ABC.webp will be treated as two different files, avoiding different files being incorrectly merged into the same cache.

  • PHP / JSP / ASP / ASPX: Do not cache
    These usually belong to dynamic pages, and setting them separately as not cached can prevent dynamic content from being cached for a long time by the CDN. For a pure image CDN, this is basically a foolproof setting.

  • Image browser cache TTL: 1 day
    jpg,png,gif,bmp,svg,webp and other images will be cached in the user's browser for 1 day. When users visit repeatedly within a short period of time, the browser can directly read the local cache, and not even EdgeOne needs to be requested again.

The final cache chain is roughly as follows:

浏览器
  ↓ 本地缓存 1 天
EdgeOne
  ↓ 节点缓存 30 天
AList
  ↓
NAS

The vast majority of repeat visits will stop at the browser or EdgeOne, and will not actually go back to the home server and NAS.

12.Self-hosted MinIO object storage

12.1.Introduction

项目 腾讯 COS 自建 MinIO
对象存储 ✅ ✅
S3 API ✅ ✅
图片/附件 ✅ ✅
Bucket ✅ ✅
SDK 上传 ✅ ✅
私有对象/签名 URL ✅ ✅
Versioning ✅ ✅
存储空间 腾讯提供 吃你服务器硬盘
带宽 腾讯提供 吃学校服务器出口带宽
高可用 腾讯负责 你负责
数据冗余 腾讯负责 你负责
硬盘损坏 云厂商处理 可能直接丢数据
运维 几乎没有 Docker、磁盘、备份、升级、安全都自己搞
费用 存储+流量 软件可以自建,但硬盘/服务器/带宽自己承担
CDN 很容易接腾讯 CDN/EO MinIO 本身不是 CDN
可控性 一般 非常高

12.2.Install

First, you need to install on the server a1panel.

Enter the store and search for MinIO.

Click to install.

Most settings can be left at their defaults, but you need to fill in the account and password yourself. As for this external access port here, if your server is on an internal network, you can choose to enable it; if your server's IP is a public IP, then it is not recommended that you enable it.

Configuration Item Recommendation
Name minio
Version Choose a stable version currently provided by 1Panel
User Set one yourself, do not use one that is too simple
Password Set a more complex password yourself
WebUI Port 9001
S3 API Port 9000
Session Duration Default 12h is fine
Enable WebUI On
WebUI Animation As you like
External Port Access It is recommended not to expose it to the public network, but if you are testing, enabling public network exposure first is also fine.

Finally, click Install.

12.3.Configure MinIO

12.3.1.Log in to MinIO

Enter in the browser服务器ip:9001:

For example, this intranet of mine10.0.0.4:9001

Then log in with the account and password.

12.3.2.Test bucket

Create a bucket, for example, here I call ittest

Let's just upload a random image and try again.

12.3.3.Test S3 protocol

The URL of the S3 protocol should be服务器ip:9000:

For example, this intranet of mine10.0.0.4:9000

Test S3 API health status on your computer:

curl -i http://10.0.0.4:9000/minio/health/live

If it showsHTTP/1.1 200 OK then it proves it is OK.

同样,测试下面这个是否S3就绪:

curl -i http://10.0.0.4:9000/minio/health/ready

If it showsHTTP/1.1 200 OK then it proves it is OK.

12.3.4.Connect to AList test

This must be kept on.

After configuration, you can return to the file list and find that the file just now can be viewed normally.