Getting started
This is a practical setup collection for CentOS Stream 9 / RHEL 9 style environments, focused on the problems that usually appear first: network setup, package sources, minimal installs, and then bringing common services online.
Before manual service configuration
VMware users: check the virtual NIC first
Make sure the virtual machine network mode is configured correctly before changing anything inside the system.

Minimal installation: what you need first
If the system was installed in minimal mode and you want it to be usable, there are a few things you should do immediately.
First, mount the ISO image:
<table> <thead> <tr> <th>1</th>
<th>mount -t iso9660 /dev/sr0 /mnt</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
After that, you can move on to local repository configuration. On a minimal install, you may also be limited to vi at first. Once the repo is available, install tab completion support, ifconfig, and vim:
1</th>
<th>yum install net-tools -y && yum install bash* -y && yum install vim -y</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Static IP configuration
Check the network interface first. In the example below, the NIC is ens160:
1 2 3 4 5 6 7 8</th>
<th>ifconfig -a #ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 # inet6 fe80::20c:29ff:fea5:d8fb prefixlen 64 scopeid 0x20<link> # ether 00:0c:29:a5:d8:fb txqueuelen 1000 (Ethernet) # RX packets 171783 bytes 191870187 (182.9 MiB) # RX errors 0 dropped 0 overruns 0 frame 0 # TX packets 25077 bytes 2147309 (2.0 MiB) # TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Edit the NetworkManager connection file:
<table> <thead> <tr> <th>1</th>
<th>vim /etc/NetworkManager/system-connections/ens160.mconnect.mconnection</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Only the IPv4 section needs to be changed in this example:
<table> <thead> <tr> <th>1 2 3 4 5</th>
<th>[ipv4] address1=192.168.50.2/24,192.168.50.1 dns=223.5.5.5 ignore-auto-dns=true method=manual</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Yum repository configuration
You can use either an online mirror or a local ISO-based repository.
Online repo
<table> <thead> <tr> <th>1</th>
<th>vim /etc/yun.repos.d/aliyun.repo</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Configuration:
<table> <thead> <tr> <th>1 2 3 4 5 6 7 8 9</th>
<th>[ali_BaseOS] name=ali_BaseOS baseurl=https://mirrors.aliyun.com/centos-stream/9-stream/BaseOS/x86_64/os/ gpgcheck=0 [ali_AppStream] name=ali_AppStream baseurl=https://mirrors.aliyun.com/centos-stream/9-stream/AppStream/x86_64/os/ gpgcheck=0</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Local repo
<table> <thead> <tr> <th>1 2 3 4 5 6 7 8 9</th>
<th>[local_BaseOS] name=local_BaseOS baseurl=file:///iso/BaseOS/ gpgcheck=0 [local_AppStream] name=ali_AppStream baseurl=file:///iso/AppStream/ gpgcheck=0</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Mount the ISO permanently
Edit /etc/fstab:
1</th>
<th>vim /etc/fstab</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Add:
<table> <thead> <tr> <th>1</th>
<th>/dev/sr0 /iso iso9660 defaults,user,ro 0 0</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Apply it immediately:
<table> <thead> <tr> <th>1</th>
<th>mount -a</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Automated setup script
There is also a shell script that automates NIC reconfiguration and repo setup. Some parts may not match every environment exactly, especially because it creates files and content using a fixed custom name. It also mentions a delayed IP replacement approach for Ansible.
<table> <thead> <tr> <th>1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64</th>
<th>#!/bin/bash # echo "anisable专供延迟" # sleep $[ ( $RANDOM % 60 + 5 ) ] namedeta="nuoyis" echo "正在修改网卡,有短暂断网现象" nuo_setnetwork_shell=$(ifconfig -a | grep -o '^\w*' | grep -v 'lo') nmcli connection delete $nuo_setnetwork_shell nmcli connection add con-name $nuo_setnetwork_shell ifname $nuo_setnetwork_shell type ethernet autoconnect yes for i in {3..254}; do ip=192.168.60.$i ping -c 2 $ip > /dev/null 2>&1 if [ $? -eq 1 ]; then nuoautoip=$ip break fi done nmcli connection modify $nuo_setnetwork_shell ipv4.method man ipv4.addresses ${nuoautoip}/24 ipv4.gateway 192.168.60.2 ipv4.dns 192.168.60.2 nmcli connection up $nuo_setnetwork_shell nmcli connection reload systemctl stop NetworkManager systemctl start NetworkManager namedeta="nuoyis" echo "配置镜像源,默认1是本地源,2是网络源" read -p "请输入你的序号:" yumid touch /etc/yum.repos.d/$namedeta.repo if [$yumid = 1];then cat > /etc/yum.repos.d/$namedeta.repo << EOF [${namedeta}_BaseOS] name = ${namedeta}_BaseOS baseurl = file:///mnt/BaseOS gpgcheck = 0 [${namedeta}_AppStream] name = ${namedeta}_AppStream baseurl = file:///mnt/AppStream gpgcheck = 0 EOF cat >> /etc/fstab << EOF /dev/sr0 /mnt iso9660 defaults,user,ro 0 0 EOF mount -a else cat > /etc/yum.repos.d/$namedeta.repo << EOF [${namedeta}_BaseOS] name = ${namedeta}_BaseOS baseurl = https://mirrors.tuna.tsinghua.edu.cn/centos-stream/9-stream/BaseOS/x86_64/os/ gpgcheck = 0 [${namedeta}_AppStream] name = ${namedeta}_AppStream baseurl = https://mirrors.tuna.tsinghua.edu.cn/centos-stream/9-stream/AppStream/x86_64/os/ gpgcheck = 0 [${namedeta}_epel] name=${namedeta}_epal baseurl=https://mirrors.tuna.tsinghua.edu.cn/epel/9/Everything/x86_64/ gpgcheck = 0 EOF fi yum update -y && yum makecache -y</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Bringing services online
Important note before you start
The following shortcut operations are only suitable when the services are not exposed to the public internet and are not being deployed in security-sensitive competition environments. Otherwise, review the security-related parts first.
1) If the service cannot be pinged or accessed
In many cases, the firewall is the reason. The following disables it and prevents it from starting at boot:
<table> <thead> <tr> <th>1 2</th>
<th>sudo systemctl disable firewall sudo systemctl stop firewall</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
2) If files cannot be read or written, or a service config does not work as expected
Check whether SELinux is permissive or disabled:
<table> <thead> <tr> <th>1 2 3 4</th>
<th>setenforce 0 或者 sudo vi /etc/selinux/config SELINUX=disabled</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
FTP service
Install and prepare vsftpd:
1 2 3 4</th>
<th>yum install vsftpd -y systemctl start systemctl enable vim /etc/vsftpd/vsftpd.conf</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Recommended configuration:
<table> <thead> <tr> <th>1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36</th>
<th># 不以独立模式运行 listen=NO # 支持 IPV6,如不开启 IPV4 也无法登录 listen_ipv6=YES # 匿名用户登录 anonymous_enable=YES no_anon_password=YES # 允许匿名用户上传文件 anon_upload_enable=YES # 允许匿名用户新建文件夹 anon_mkdir_write_enable=YES # 匿名用户删除文件和重命名文件 anon_other_write_enable=YES # 匿名用户的掩码(022 的实际权限为 666-022=644) anon_umask=022 anon_root=/ftp/anon # 系统用户登录 local_enable=YES local_umask=022 local_root=/madia/ftp/user chroot_local_user=YES allow_writeable_chroot=YES chroot_list_enable=YES chroot_list_file=/etc/vsftpd/chroot_list # 对文件具有写权限,否则无法上传 write_enable=YES max_clients=0 max_per_ip=0 # 使用主机时间 use_localtime=YES pam_service_name=vsftpd</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
This setup enables both anonymous and local-user access, allows anonymous uploads and directory creation, and chroots local users.
Apache service
Install Apache HTTP Server:
<table> <thead> <tr> <th>1 2 3 4</th>
<th>yum install httpd -y systemctl start httpd systemctl enable httpd vim /etc/httpd/conf/httpd.conf</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Configuration example:
<table> <thead> <tr> <th>1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52</th>
<th>ServerRoot "/etc/httpd" Listen 80 Listen 8080 Include conf.modules.d/*.conf User apache Group apache ServerAdmin root@localhost <Directory /> AllowOverride none Require all denied </Directory> DocumentRoot "/var/www/html" <Directory "/var/www"> AllowOverride None Require all granted </Directory> LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio </IfModule> CustomLog "logs/access_log" combined </IfModule> <IfModule alias_module> ScriptAlias /cgi-bin/ "/var/www/cgi-bin/" </IfModule> <Directory "/var/www/cgi-bin"> AllowOverride None Options None Require all granted </Directory> <IfModule mime_module> TypesConfig /etc/mime.types AddType application/x-compress .Z AddType application/x-gzip .gz .tgz AddType text/html .shtml AddOutputFilter INCLUDES .shtml </IfModule> AddDefaultCharset UTF-8 <IfModule mime_magic_module> MIMEMagicFile conf/magic </IfModule> EnableSendfile on IncludeOptional conf.d/*.conf <VirtualHost *:80> ServerName 0.0.0.0 DocumentRoot /var/www/nuoyis </VirtualHost></th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
The example listens on both ports 80 and 8080 and defines a virtual host whose document root is /var/www/nuoyis.
Samba service
Install Samba:
<table> <thead> <tr> <th>1 2 3 4</th>
<th>yum install samba* -y systemctl start smb systemctl enable smb vim /etc/samba/smb.conf</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Add this share definition at the end of the config:
<table> <thead> <tr> <th>1 2 3 4 5 6</th>
<th>[nuoyis] comment = xxxx samba share path = /media/nuoyis/ writable = yes browseable = yes guest ok = yes</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Then create a user and add the Samba password:
<table> <thead> <tr> <th>1 2 3</th>
<th>useradd nuoyis1024 passwd nuoyis1024 smbpasswd -a nuoyis1024</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
NFS service
The notes for NFS focus on the basic export format and startup order:
<table> <thead> <tr> <th>1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16</th>
<th>yum install rpcbind -y systemctl start rpcbind systemctl enable rpcbind NFS的配置文件为 /etc/exports,文件内容默认为空。在设置共享资源时,格式为: 目录位置 客户机地址(权限选项) (1) 例如,若要将文件夹/opt/web 共享给192.168.100.120主机使用,允许读操作: [root@localhost ~]# vi /etc/exports /opt/web 192.168.100.120(ro) //ro表示只读权限 (2) 若要将同一个目录给两个不同的主机,且分配不同的权限时,只要以空格分隔指定多个“客户机(权限选项)”即可。 例如,若要将/var/ftp/pubilc 目录共享给两个客户机,分别给予只读、读写权限: [root@localhost ~]# vi /etc/exports /var/ftp/pub 192.168.1.54(ro) 192.168.1.77(rw) //rw表示读写权限 重启NFS,注意:手动加载NFS共享服务时,应该先启动rpcbind,然后再启动nfs。 showmount -e //查看本机共享文件目录</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Key points:
- The NFS export file is
/etc/exports. - The format is
directory client(options). romeans read-only,rwmeans read-write.- If loading services manually, start
rpcbindbeforenfs. - Use
showmount -eto view exported directories.
DHCP service
Install DHCP server:
<table> <thead> <tr> <th>1 2 3 4</th>
<th>yum install dhcpd -y systemctl start dhcpd systemctl enable dhcpd vim /etc/dhcp/dhcpd.conf</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
The quickest way to start is to copy the sample config:
<table> <thead> <tr> <th>1</th>
<th>cp /usr/share/doc/dhcp-server/dhcpd.conf.example /etc/dhcp/dhcpd.conf</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
A typical configuration includes a dynamic scope and, if needed, static reservation entries:
<table> <thead> <tr> <th>1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16</th>
<th># 动态配置 # 分别是网段范围,分配的ip范围,网关,广播地址,域名解析,更新时间 subnet 192.168.50.0 netmask 255.255.255.0 { range 192.168.50.11 192.168.50.250; option routers 192.168.50.1; option broadcast-address 192.168.50.255; option domain-name-servers 192.168.50.1; default-lease-time 600; max-lease-time 7200; } # 静态解析,以web服务器为例 host www { hardware ethernet 网卡mac; fixed-address 192.168.100.80; }</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
The example scope defines the subnet, lease range, gateway, broadcast address, DNS server, and lease duration. It also shows how to bind a fixed address to a specific MAC address.
DNS service
Install BIND:
<table> <thead> <tr> <th>1 2 3 4</th>
<th>yum install bind -y systemctl start bind systemctl enable bind vim /etc/named.conf</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
If the DNS server only needs to serve machines on the internal network, replacing 127.0.0.1 and localhost with any is enough in the relevant settings.
For internal-domain use, the client resolver should point to the internal DNS server. Example:
[root@DNS-user /]# cat /etc/resolv.conf
# Generated by NetworkManager
search localdomain
nameserver 192.168.50.1
MariaDB service
Install and enable MariaDB:
<table> <thead> <tr> <th>1 2 3</th>
<th>yum install Mariadb -y systemctl start Mariadb systemctl enable Mariadb</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Firewalld rules
If you do need to keep the firewall enabled, use service-based rules:
firewall-cmd –zone=public –add-service=服务名 –per
SELinux policy checks
To inspect service-related SELinux booleans:
getsebool -a | grep 服务名
Basic Ansible operations
Install Ansible:
<table> <thead> <tr> <th>1 2 3</th>
<th>yum install Ansible -y systemctl start Ansible systemctl enable Ansible</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Docker service
Quick script
<table> <thead> <tr> <th>1</th>
<th>curl -fsSL get.docker.com -o get-docker.sh</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Manual installation
Run this first:
<table> <thead> <tr> <th>1</th>
<th>yum install docker-ce -y</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
If the package cannot be found, configure the Docker repository first:
<table> <thead> <tr> <th>1 2 3 4</th>
<th>yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo yum makecache</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
This switches the default Docker repo to the Tsinghua mirror and rebuilds the cache before retrying installation.