rocky Linux 环境安装加固,PostgreSQL手动编译安装

0 阅读6分钟

本来准备写聚合函数呢,突然发现自己已经好久没开过的虚拟机了。我现在手上的环境还是centos呢..... centos都EOL两年了。嘴炮不可取,还是要在实际环境上跑一跑的。话不多说,直接上菜:

首先是环境的下载链接

VMware workstation:官网开始要登录了,再也不是以前的好宝了,软件和激活码自己去网站上找一个,实在不行腾讯火萤等软件商店里也有。

Rocky Linux minimal系统:https://download.rockylinux.org/pub/rocky/9/isos/x86_64/Rocky-9.7-x86_64-minimal.iso

Linux的安装

这个基本没啥讲的,安装VMware,打开软件,创建新的虚拟机,导入iso镜像,剩下的就是等了..... 唯一注意的点是在分区的时候,提前设置好自定义分区。不然按照默认建好后所有空间都挂在根目录上没法分就尴尬了。我是这么分的,仅作参考

image.png

系统加固

正常来说可以分为 root加固, sshd 加固, 防火墙加固,辅助功能安装,yum源配置,这几大块。不过这是我自己的机器,有些细节我就不做了,比如设置密钥登录, 禁止root登录等.... 我会在指令行里写出来怎么做

0.先把ssh远程连接打开
vi /etc/sshd/sshd_config

PasswordAuthentication  yes
PermitRootLogin  yes

systemctl resatart sshd
1.root 加固
--1. 设置root密码(如果还没设)
sudo passwd root

# 创建用户(比如叫 lee)
sudo useradd -m -s /bin/bash lee
# 设置密码
sudo passwd lee

# 组设置现在流行一个用户一个组的UPG的模式。默认设好不用管,不过可以给个加组的指令(可选)
sudo usermod -aG jack tomq

权限配置:
所有者 → 组 → 其他人

符号	含义	英文
u	所有者	user
g	所属组	group
o	其他人	others
a	所有人	all(= u+g+o)
操作符:+ 添加、- 移除、= 精确设置

#加权限的三种方式
chmod u=rwx,g=rx,o=r file.txt
chomod 755 file.txt
chmod  u+rwx file.txt

r	读	4	读取文件/列出目录
w	写	2	修改文件/创建删除文件
x	执行	1	运行程序/进入目录
2. sshd 加固
1. 修改监听端口(从22改成比如2222)
bash
sudo sed -i 's/^#\?Port 22/Port 2222/' /etc/ssh/sshd_config 

# 如果没有就添加
echo "Port 2222" | sudo tee -a /etc/ssh/sshd_config


2. 禁用空密码登录
bash
sudo sed -i 's/^#PermitEmptyPasswords no/PermitEmptyPasswords no/' /etc/ssh/sshd_config
或者
echo "PermitEmptyPasswords no" | sudo tee -a /etc/ssh/sshd_config


3. 禁用DNS反向解析(加快连接速度)
bash
echo "UseDNS no" | sudo tee -a /etc/ssh/sshd_config


4. 设置最大尝试次数
bash
echo "MaxAuthTries 3" | sudo tee -a /etc/ssh/sshd_config


5. 禁止root直接SSH登录(重要)
sudo sed -i 's/^#\?PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config  
# 如果没有这行就手动添加
echo "PermitRootLogin no" | sudo tee -a /etc/ssh/sshd_config 


6. 重启SSH服务使配置生效(所有设置完再执行,不然链接断了就尴尬了)
bash
sudo systemctl restart sshd 


7. 记得检查semanage, 至少rocky的linux需要(大概率没装)
yum list | grep policycoreutils
yum install -y policycoreutils-python-utils

查看当前 SSH 允许的端口列表
sudo semanage port -l | grep ssh

把 2222 添加到 SSH 端口类型
sudo semanage port -a -t ssh_port_t -p tcp 2222

或者把semannge给关了
vi /etc/selinux/config
SELINUX=disabled

然后重启
reboot

注:排查流程
1. ss -lntp | grep sshd 看不到新的sshd的端口
2. systemctl status sshd 看到sshd的状态active,但是偶有报错
3. sudo journalctl -u sshd -n 20 --no-pager 能看到新端口是permission denied.
3. 防火墙加固(启用,可选)
三、防火墙配置
直接关了
systemctl stop firewalld
永久关闭
systemctl disable firewalld

查看配置文件
/etc/sysconfig/iptables

或者
# 先允许新端口,再关闭旧端口
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --permanent --remove-port=22/tcp
sudo firewall-cmd --reload

等下有其他端口对外开放的话,记得打墙
4.辅助功能设置
# 1.修改主机名
sudo hostnamectl set-hostname db-lab
或者
vi /etc/hostname 

# 2.编辑hosts文件
sudo vim /etc/hosts
# 添加一行:127.0.1.1 db-lab


更新系统
# CentOS/RHEL
sudo yum update -y


3. 安装基础工具
# CentOS/RHEL
sudo yum install -y vim curl wget net-tools
5.配置密钥登录 (可选,我没搞)
Windows宿主机上执行:
powershell
# 生成密钥对(如果还没有)
ssh-keygen -t ed25519 -C "vmware-lab"

# 查看公钥内容
type $env:USERPROFILE\.ssh\id_ed25519.pubLinux虚拟机中执行:
bash
# 以lab用户登录后
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# 把上面看到的公钥内容添加到这个文件
nano ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

禁用密码登录(可选,做完上面密钥认证后)
sudo sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
echo "PasswordAuthentication no" | sudo tee -a /etc/ssh/sshd_config
sudo systemctl restart sshd
6.yum源配置
# 1. 备份原有源
sudo mkdir -p /etc/yum.repos.d/backup
sudo cp -r /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/

# 2. 下载/创建新的源文件
sudo wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo

# 对我们来说,需要添加额外的数据库源
yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

# 或者手动
sudo tee /etc/yum.repos.d/pgdg.repo > /dev/null << 'EOF'
[pgdg15]
name=PostgreSQL 15 for RHEL/Rocky 9 - x86_64
baseurl=https://download.postgresql.org/pub/repos/yum/15/redhat/rhel-9-x86_64
enabled=1
gpgcheck=1
gpgkey=https://download.postgresql.org/pub/repos/yum/RPM-GPG-KEY-PGDG
repo_gpgcheck=0
EO
注:不同linux版本记得name和url的版本名字

# 3. 清理缓存
sudo yum clean all

# 4. 重新生成缓存
sudo yum makecache

# 5. 看新开的仓库
yum repolist
Postgres的数据库安装

正常来说数据库安装是很简单的,配好yum源,一个yum install指令结束。就像下面这样,四条指令结束战斗,然后就可以使用了。

# 在线配置yum源
yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

# 更新一下 yum 缓存
sudo yum update

# 安装 PostgreSQL 15 的服务器端和常用扩展包
sudo yum install -y postgresql15-server postgresql15-contrib

# 初始化数据库
sudo /usr/pgsql-15/bin/postgresql-15-setup initdb

#启动并设置开机自启
sudo systemctl enable --now postgresql-15

# 上指令开测
sudo -u postgres psql

但这种方式是机械的,固定的,没有灵魂的♂, 没有diy的乐趣的。在我们遇见的数据库生产环境中,一般都是有自己的数据程序和目录的,比如一般程序在/opt, 数据在/data下。目前云环境数据库一般就是这么搞的,一个发行的rpm包,里面是编译好的数据库二进制文件,附带了数据库的程序和相关的数据库安装依赖。里面安装目录和数据目录实在编译rpm的时候直接固定好的,属于发行商固定的自定义安装目录。

这种一般是使用rpmbuild进行编译的,下载或者使用自己的源码包,通过rpmbuild打成一个可以离线安装的数据库包,一般是配合着模板机同时使用的。由于可以控制目标机器和模板机版本型号,内存路径等关键内容完全一致,可以有效保证安装数据库的成功率。

当然,也有完全可以用户自定义安装路径的。这种一般是一个tar包,里面一般是有一个程序包,和一个安装脚本,类似installer.sh,一般脚本用来进行命令交互,用来设置路径啊,内存啊,日志啊,等相关参数。

今天我们先搞定如何使用rpm包来安装数据库,包括如何配置环境,制作模板机,编译rpm包,环境安装,等等。我刚开始工作的时候接触的是这种rpm包。男人嘛,总是对自己的第一次印象深刻的😁

1. 首先是配置rpmbuild的编译环境
# 安装rpmbuild环境和对应依赖
sudo yum install -y rpm-build gcc make readline-devel zlib-devel openssl-devel bison flex

# 创建对应的rpmbuild对应的目录
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}

# 检查对应的目录
rpmbuild --version
which rpmbuild
ls -la ~/rpmbuild/

# 正常状态下,目录标准
~/rpmbuild/
├── BUILD/      # 源码解压和编译目录
├── RPMS/       # 生成的二进制 RPM 包存放位置
├── SOURCES/    # 原始源码、补丁文件
├── SPECS/      # .spec 打包脚本文件
└── SRPMS/      # 生成的源码 RPM 包存放位置

2. 下载对应的源程序包
# 将源码包放到对应的文件夹下

cd ~/rpmbuild/SOURCES
wget https://ftp.postgresql.org/pub/source/v15.17/postgresql-15.17.tar.gz
3. 编写测试spec文件
[root@db-lab SPECS]# cat ~/rpmbuild/SPECS/postgresql-customer.spec

# 基础定义

#关掉debug包
%global debug_package %{nil}

Name:           postgresql-custom
Version:        15.17
Release:        1%{?dist}
Summary:        PostgreSQL server with fixed paths (/opt/pgsql, /data/pgsql)
License:        PostgreSQL
URL:            https://www.postgresql.org/

Source0:        postgresql-%{version}.tar.gz
BuildRequires:  gcc, make, readline-devel, zlib-devel, openssl-devel, bison, flex
Requires(pre):  shadow-utils

%description
PostgreSQL server compiled for fixed installation paths:
- Program files: /opt/pgsql
- Data directory: /data/pgsql/data
A random password will be generated for 'postgres' user during installation.

%prep
%autosetup -n postgresql-%{version}

%build
./configure \
    --prefix=/opt/pgsql \
    --sysconfdir=/opt/pgsql/etc \
    --localstatedir=/data/pgsql/data \
    --with-openssl \
    CFLAGS="-O2"
make -j$(nproc) world

%install
rm -rf %{buildroot}
make install-world DESTDIR=%{buildroot}
mkdir -p %{buildroot}/data/pgsql/data
mkdir -p %{buildroot}/opt/pgsql/etc
mkdir -p %{buildroot}/etc/systemd/system          
rm -rf %{buildroot}/data/pgsql/data/* 2>/dev/null || true

cat > %{buildroot}/etc/systemd/system/postgresql.service <<'EOF'
[Unit]
Description=PostgreSQL Custom Server
After=network.target

[Service]
Type=forking
User=postgres
Group=postgres
ExecStart=/opt/pgsql/bin/pg_ctl start -D /data/pgsql/data
ExecStop=/opt/pgsql/bin/pg_ctl stop -D /data/pgsql/data
ExecReload=/opt/pgsql/bin/pg_ctl reload -D /data/pgsql/data
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

%pre
getent group postgres >/dev/null || groupadd -r postgres
if ! getent passwd postgres >/dev/null; then
    useradd -m -r -g postgres -d /home/postgres -s /bin/bash postgres
fi
exit 0

%post
# 环境变量配置(仅 postgres 用户)
cat > /home/postgres/.bashrc <<'EOF'
export PATH=/opt/pgsql/bin:$PATH
export PGDATA=/data/pgsql/data
export PGPORT=5432
export PGHOST=/tmp
export PGUSER=postgres
export PGDATABASE=postgres
export LANG=en_US.UTF-8
EOF
chown postgres:postgres /home/postgres/.bashrc
chmod 644 /home/postgres/.bashrc


# 确保 /opt/pgsql 存在且归 postgres 所有
if [ ! -d /opt/pgsql ]; then
    echo "ERROR: /opt/pgsql not found. Installation may be incomplete." >&2
    exit 1
fi
chown -R postgres:postgres /opt/pgsql 2>/dev/null || true

# 确保 /opt/pgsql 存在
PGDATA_DIR="/data/pgsql/data"

# 如果目录非空,清空它(适用于全新部署)
if [ -d "$PGDATA_DIR" ] && [ "$(ls -A $PGDATA_DIR 2>/dev/null)" ]; then
    echo "WARNING: $PGDATA_DIR not empty. Cleaning it for fresh initdb."
    rm -rf $PGDATA_DIR/*
    rm -rf $PGDATA_DIR/.[!.]* 2>/dev/null || true 
fi

mkdir -p $PGDATA_DIR
chown postgres:postgres $PGDATA_DIR
chmod 700 $PGDATA_DIR


# 初始化
su - postgres -c "/opt/pgsql/bin/initdb -D $PGDATA_DIR -U postgres --auth-local=trust --auth-host=scram-sha-256"


cat >> $PGDATA_DIR/postgresql.conf <<EOF
listen_addresses = '*'
port = 5432
EOF

systemctl daemon-reload
systemctl enable postgresql
systemctl start postgresql

# 等待 PostgreSQL 真正启动(最多等待30秒)
for i in {1..30}; do
    if su - postgres -c "/opt/pgsql/bin/pg_isready -q"; then
        break
    fi
    sleep 1
done

PASSWORD=$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 12)
echo "$PASSWORD" > $PGDATA_DIR/.pgpass_temp
chown postgres:postgres $PGDATA_DIR/.pgpass_temp
chmod 600 $PGDATA_DIR/.pgpass_temp

cat > /tmp/set_pwd.sql <<EOF
ALTER USER postgres WITH PASSWORD '$PASSWORD';
EOF
su - postgres -c "/opt/pgsql/bin/psql -d postgres -f /tmp/set_pwd.sql"
rm -f /tmp/set_pwd.sql


echo "PostgreSQL installed. Random password for user 'postgres': $PASSWORD" | logger -t postgres-install
echo "Password also saved in $PGDATA_DIR/.pgpass_temp (root read only)"

%preun
if [ $1 -eq 0 ]; then
    systemctl stop postgresql >/dev/null 2>&1 || true
    systemctl disable postgresql >/dev/null 2>&1 || true
fi

%postun
if [ $1 -eq 0 ]; then
    rm -f /etc/systemd/system/postgresql.service
    systemctl daemon-reload
    systemctl reset-failed

    # 删数据、删用户、删家目录
    rm -rf /data/pgsql /home/postgres
    userdel -r postgres 2>/dev/null || true   
    groupdel postgres 2>/dev/null || true

    echo "PostgreSQL completely removed (including data and user)"
fi

%files
%defattr(-,root,root)
/opt/pgsql
/data/pgsql
/etc/systemd/system/postgresql.service 

4. 运行rpmbuild生成rpm包
# 开始运行环境
cd ~/rpmbuild/SPECS
rpmbuild -bb postgresql-custom.spec

image.png

5. 目标机器上执行rpm包
# 文件传输到目标机上,r
scp -P 2222 root@192.168.183.130:/root/rpmbuild/RPMS/x86_64/postgresql-custom-15.17-1.el9.x86_64.rpm /var/
rpm -ivh /var/postgresql-custom-15.17-1.el9.x86_64.rpm

image.png

6. 测试验证
su - postgres

[postgres@localhost ~]$ psql
psql (15.17)
Type "help" for help.

postgres=# show version;
ERROR:  unrecognized configuration parameter "version"
postgres=#
postgres=#
postgres=#
postgres=# select version();

image.png

最后只能说,感谢AI,感谢DeepSeek,我对SPEC是真的不熟,只知道有这个玩意,可以用来编译安装包。要是没AI协助帮忙,单是这个脚本我就得连写带调半个月。还有要善用工具,但不要让你变成工具的人,这个时代不接触AI是老古董,完全相信AI是大傻子。 这个脚本一开始里面简直没法看,只能说结构是对的,细节是一坨,后面我用deepseek加上我自己调试了两天才算勉强满意,算是AI省了我手写的功夫了。 最后豆包是真的菜,专业技术上不要相信她。