新服务器初始化 2

ℹ️ Note 又剁手搞了台小鸡,重温一下服务器初始化 参考文章 Linux服务器的初步配置流程 - 阮一峰的网络日志 之前我写的 博客服务器初始化 | 安落滢 Blog但是写的比较简单,这次稍微整理一下格式和一些细节,并且加上一些安全配置 那么文章是老文章了,所以新的流程会有一丢丢变化,可以偷一些懒 📌 前提 本文假设你已经: 安装好最新的 Ubuntu Server LTS(例如 Ubuntu 24.04 LTS 或 22.04 LTS)系统;参考官方安装流程可以先完成基本安装和网络配置。 有 root 或 sudo 权限来执行系统初始化操作。 步骤 内容 登录 & 用户 创建普通用户、禁用 root SSH 系统更新 更新升级及自动安全升级 安全配置 SSH 强化、UFW、Fail2Ban 系统增强 Chrony、Audit、安全扫描 其他 时区、Swap、常用工具 🚀 一、首次登录 & 用户账号设定 1. 登录服务器 1 ssh root@your_server_ip 如果是云主机一般默认创建了一个 sudo 用户,可以直接用该用户登录,而不要直接用 root 登录。 我一般喜欢改个 hostname 和时区 1 2 hostnamectl set-hostname <new-hostname> sudo timedatectl set-timezone Asia/Hong_Kong 2. 创建新用户(避免日常使用 root) 1 2 sudo adduser youruser sudo usermod -aG sudo youruser 👉 将 youruser 换成你自己的管理用户名。 ...

December 15, 2025 · 2 min · 318 words · Ray

tar 包爆炸了

很狼狈的一件事情,到手一个 tar 压缩包之后。直接运行 tar -xvf 罪魁祸首.tar 结果就像一个在我混乱的卧室里 爆开一包薯片一样,撒的到处都是,一点点捡可能还捡不干净,有一些文件的修改日期十分远古,看不出来是否来自压缩包内 首先,快捷查看包内容可以使用 tar -tf myfile.tgz 或者 -tzf -t(或 –list)表示列出内容。 -z 表示使用 gzip 解压(因为 .tgz 通常是 .tar + gzip 压缩) -f 指定档案文件。 如果想看得更 “详细”(包括权限、时间戳、大小等),可以加 -v: 1 2 3 (base) yangr@172-16-99-32-Dev:/data/yangr$ tar -tf meetingasr.tgz meetingasr/ meetingasr/app/ 这样可以看到包里的顶层是一个文件夹,而不是那一堆薯片碎,现在直接解压会在当前目录解压到这个名字的文件夹内 但是,如果某一天忘记看一眼里面的结构,我之前会使用 -C 参数 change to directory tar -xzf archive.tgz -C /path/to/targetdir 但是这个参数需要先有指定的目录才能执行,这很麻烦 所以还有一个方案就是使用 --one-top-level tar -xzf myfile.tgz --one-top-level=newdir 这样无论包里是什么结构,都会把内容解压到 newdir/ 目录内。 那如果我已经是上面例子 有一个文件夹,那岂不是会变成 newdir/meetingasr/ 了 所以还能用 tar -xzf myfile.tgz --strip-components=1 剥掉包里路径的第一级目录 ...

November 12, 2025 · 1 min · 73 words · Ray

Harbor push unauthorized

Harbor push unauthorized 我真的快没招了,这个东西折磨了我很久了 具体是什么情况 如下 1 2 3 4 docker push hub.szmckj.cn/hotpotcat/perm-check:zz The push refers to repository [hub.szmckj.cn/hotpotcat/perm-check] 17eec7bbc9d7: Unavailable error from registry: unauthorized to access repository: hotpotcat/perm-check, action: push: unauthorized to access repository: hotpotcat/perm-check, action: push 如这里所见。我在公司的服务器上装了 VMware Harbor 来多地同步docker镜像,同时存一些基本镜像避免网络问题。 但是无论我在哪里都愉快使用的时候,在家里的Windows遇到了这个 无法push的问题 首先在Harbor的配置处 我检查了项目名称,全小写,一个字母没错,我检查了登录的用户。是我在UI登录的账号密码。我logout再login 也依旧报错。我检查了 项目的策略。这是一个干净的仓库,创建人是我,并且我上午在公司的mac 和 ubuntu服务器成功推送过。 甚至他是个公开仓库啊 怀疑系统,用wsl试试 还是这样 怀疑代理问题 关了clash,切换了旁路由,还是这样子 gpt叫我搞个机器人账号试试 我都拉满权限了还是这样 看后台日志 到这一步我其实严重怀疑是网络问题。但是我没证据所以还是先看后台日志,好在看了 显示已折叠代码(29 行) 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 registry | ::1 - - [29/Oct/2025:15:38:14 +0000] "GET / HTTP/1.1" 200 0 "" "curl/8.12.0" nginx | 127.0.0.1 - "GET / HTTP/1.1" 200 785 "-" "curl/8.12.0" 0.001 0.001 . harbor-portal | 172.31.0.9 - - [29/Oct/2025:15:38:17 +0000] "GET / HTTP/1.1" 200 785 "-" "curl/8.12.0" registry | 172.31.0.4 - - [29/Oct/2025:15:38:19 +0000] "GET / HTTP/1.1" 200 0 "" "Go-http-client/1.1" harbor-portal | 172.31.0.4 - - [29/Oct/2025:15:38:19 +0000] "GET / HTTP/1.1" 200 785 "-" "Go-http-client/1.1" registryctl | 172.31.0.4 - - [29/Oct/2025:15:38:19 +0000] "GET /api/health HTTP/1.1" 200 9 nginx | 172.16.99.6 - "HEAD /v2/hotpotcat/perm-check/blobs/sha256:17eec7bbc9d79fa397ac95c7283ecd04d1fe6978516932a3db110c6206430809 HTTP/1.1" 401 0 "-" "docker/28.4.0 go/go1.24.7 git-commit/249d679 kernel/6.6.87.2-microsoft-standard-WSL2 os/linux arch/amd64 containerd-client/2.1.4+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.4.0 \x5C(windows\x5C))" 0.003 0.003 . nginx | 172.16.99.6 - "HEAD /v2/hotpotcat/perm-check/blobs/sha256:1b44b5a3e06a9aae883e7bf25e45c100be0bb81a0e01b32de604f3ac44711634 HTTP/1.1" 401 0 "-" "docker/28.4.0 go/go1.24.7 git-commit/249d679 kernel/6.6.87.2-microsoft-standard-WSL2 os/linux arch/amd64 containerd-client/2.1.4+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.4.0 \x5C(windows\x5C))" 0.005 0.005 . nginx | 172.16.99.6 - "POST /service/token HTTP/1.1" 405 19 "-" "containerd/2.1.4+unknown" 0.002 0.001 . harbor-core | 2025-10-29T15:38:26Z [INFO] [/server/middleware/security/robot.go:71][requestID="55026fa7-8ad3-4fac-a387-d3db6484ac5c" traceID="aa950751535cc6b087bf5ec533951b10"]: a robot security context generated for request GET /service/token nginx | 172.16.99.6 - "GET /service/token?scope=repository%3Ahotpotcat%2Fperm-check%3Apull&scope=repository%3Ahotpotcat%2Fperm-check%3Apull%2Cpush&service=harbor-registry HTTP/1.1" 200 1010 "-" "containerd/2.1.4+unknown" 0.025 0.025 . nginx | 172.16.99.6 - "HEAD /v2/hotpotcat/perm-check/blobs/sha256:1b44b5a3e06a9aae883e7bf25e45c100be0bb81a0e01b32de604f3ac44711634 HTTP/1.1" 404 0 "-" "docker/28.4.0 go/go1.24.7 git-commit/249d679 kernel/6.6.87.2-microsoft-standard-WSL2 os/linux arch/amd64 containerd-client/2.1.4+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.4.0 \x5C(windows\x5C))" 0.005 0.005 . nginx | 172.16.99.6 - "HEAD /v2/hotpotcat/perm-check/blobs/sha256:17eec7bbc9d79fa397ac95c7283ecd04d1fe6978516932a3db110c6206430809 HTTP/1.1" 404 0 "-" "docker/28.4.0 go/go1.24.7 git-commit/249d679 kernel/6.6.87.2-microsoft-standard-WSL2 os/linux arch/amd64 containerd-client/2.1.4+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.4.0 \x5C(windows\x5C))" 0.022 0.023 . registry | time="2025-10-29T15:38:26.164978329Z" level=info msg="authorized request" go.version=go1.23.8 http.request.host="hub.szmckj.cn:443" http.request.id=e560674b-c756-457d-8294-cbc6e4d85504 http.request.method=POST http.request.remoteaddr=116.30.100.87 http.request.uri="/v2/hotpotcat/perm-check/blobs/uploads/" http.request.useragent="docker/28.4.0 go/go1.24.7 git-commit/249d679 kernel/6.6.87.2-microsoft-standard-WSL2 os/linux arch/amd64 containerd-client/2.1.4+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.4.0 \(windows\))" vars.name="hotpotcat/perm-check" registry | time="2025-10-29T15:38:26.168010906Z" level=info msg="response completed" go.version=go1.23.8 http.request.host="hub.szmckj.cn:443" http.request.id=e560674b-c756-457d-8294-cbc6e4d85504 http.request.method=POST http.request.remoteaddr=116.30.100.87 http.request.uri="/v2/hotpotcat/perm-check/blobs/uploads/" http.request.useragent="docker/28.4.0 go/go1.24.7 git-commit/249d679 kernel/6.6.87.2-microsoft-standard-WSL2 os/linux arch/amd64 containerd-client/2.1.4+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.4.0 \(windows\))" http.response.duration=11.300209ms http.response.status=202 http.response.written=0 registry | 172.31.0.4 - - [29/Oct/2025:15:38:26 +0000] "POST /v2/hotpotcat/perm-check/blobs/uploads/ HTTP/1.1" 202 0 "" "docker/28.4.0 go/go1.24.7 git-commit/249d679 kernel/6.6.87.2-microsoft-standard-WSL2 os/linux arch/amd64 containerd-client/2.1.4+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.4.0 \\(windows\\))" nginx | 172.16.99.6 - "POST /v2/hotpotcat/perm-check/blobs/uploads/ HTTP/1.1" 202 0 "-" "docker/28.4.0 go/go1.24.7 git-commit/249d679 kernel/6.6.87.2-microsoft-standard-WSL2 os/linux arch/amd64 containerd-client/2.1.4+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.4.0 \x5C(windows\x5C))" 0.022 0.021 . nginx | 172.16.99.6 - "PUT /v2/hotpotcat/perm-check/blobs/uploads/9d9e11fd-abe0-456e-9b9c-d5da9a020239?_state=MvL4ZmK09_2yH7zJzwMYeiWVk_vgc4FBa4AHfNLaNs97Ik5hbWUiOiJob3Rwb3RjYXQvcGVybS1jaGVjayIsIlVVSUQiOiI5ZDllMTFmZC1hYmUwLTQ1NmUtOWI5Yy1kNWRhOWEwMjAyMzkiLCJPZmZzZXQiOjAsIlN0YXJ0ZWRBdCI6IjIwMjUtMTAtMjlUMTU6Mzg6MjYuMTY1MTIxNTg2WiJ9&digest=sha256%3A1b44b5a3e06a9aae883e7bf25e45c100be0bb81a0e01b32de604f3ac44711634 HTTP/1.1" 401 190 "-" "docker/28.4.0 go/go1.24.7 git-commit/249d679 kernel/6.6.87.2-microsoft-standard-WSL2 os/linux arch/amd64 containerd-client/2.1.4+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.4.0 \x5C(windows\x5C))" 0.003 0.003 . registry | time="2025-10-29T15:38:26.184206457Z" level=info msg="authorized request" go.version=go1.23.8 http.request.host="hub.szmckj.cn:443" http.request.id=487e9723-c8f5-4646-af27-b301329de187 http.request.method=POST http.request.remoteaddr=116.30.100.87 http.request.uri="/v2/hotpotcat/perm-check/blobs/uploads/" http.request.useragent="docker/28.4.0 go/go1.24.7 git-commit/249d679 kernel/6.6.87.2-microsoft-standard-WSL2 os/linux arch/amd64 containerd-client/2.1.4+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.4.0 \(windows\))" vars.name="hotpotcat/perm-check" registry | 172.31.0.4 - - [29/Oct/2025:15:38:26 +0000] "POST /v2/hotpotcat/perm-check/blobs/uploads/ HTTP/1.1" 202 0 "" "docker/28.4.0 go/go1.24.7 git-commit/249d679 kernel/6.6.87.2-microsoft-standard-WSL2 os/linux arch/amd64 containerd-client/2.1.4+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.4.0 \\(windows\\))" registry | time="2025-10-29T15:38:26.186531266Z" level=info msg="response completed" go.version=go1.23.8 http.request.host="hub.szmckj.cn:443" http.request.id=487e9723-c8f5-4646-af27-b301329de187 http.request.method=POST http.request.remoteaddr=116.30.100.87 http.request.uri="/v2/hotpotcat/perm-check/blobs/uploads/" http.request.useragent="docker/28.4.0 go/go1.24.7 git-commit/249d679 kernel/6.6.87.2-microsoft-standard-WSL2 os/linux arch/amd64 containerd-client/2.1.4+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.4.0 \(windows\))" http.response.duration=10.154146ms http.response.status=202 http.response.written=0 nginx | 172.16.99.6 - "POST /v2/hotpotcat/perm-check/blobs/uploads/ HTTP/1.1" 202 0 "-" "docker/28.4.0 go/go1.24.7 git-commit/249d679 kernel/6.6.87.2-microsoft-standard-WSL2 os/linux arch/amd64 containerd-client/2.1.4+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.4.0 \x5C(windows\x5C))" 0.022 0.022 . registry | 172.31.0.4 - - [29/Oct/2025:15:38:29 +0000] "GET / HTTP/1.1" 200 0 "" "Go-http-client/1.1" registryctl | 172.31.0.4 - - [29/Oct/2025:15:38:29 +0000] "GET /api/health HTTP/1.1" 200 9 harbor-portal | 172.31.0.4 - - [29/Oct/2025:15:38:29 +0000] "GET / HTTP/1.1" 200 785 "-" "Go-http-client/1.1" harbor-portal | 127.0.0.1 - - [29/Oct/2025:15:38:33 +0000] "GET / HTTP/1.1" 200 785 "-" "curl/8.12.0" registryctl | ::1 - - [29/Oct/2025:15:38:33 +0000] "GET /api/health HTTP/1.1" 200 9 registry | 172.31.0.4 - - [29/Oct/2025:15:38:39 +0000] "GET / HTTP/1.1" 200 0 "" "Go-http-client/1.1" harbor-portal | 172.31.0.4 - - [29/Oct/2025:15:38:39 +0000] "GET / HTTP/1.1" 200 785 "-" "Go-http-clien 这是进行push时看到的日志。太长啦。感谢G老师再次拯救我 G老师分析如下 ...

October 29, 2025 · 4 min · 698 words · Ray

给ssh登录做一个通知

给ssh登录做一个通知 钉钉创建一个群。然后创建一个普通机器人。 这个思路是自己想的,随手搜了一下 真有佬做了.下面是链接 如何使用钉钉机器人通知接收服务器SSH登录提醒 - 阿豪运维笔记 根据佬的写法 后面再加点功能。最近忙的紧,先把这个脚本部署尝试 主要原理就是sshrc是SSH服务的一个特殊文件,它会在每次SSH会话建立时自动执行。 执行时获取一些信息,执行 POST 请求 到钉钉的 webhook 地址,群里的机器人就可以发消息了 注意关键词的设置 [sh] 显示已折叠代码(70 行) 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 65 66 67 68 69 70 # 编辑/etc/ssh/sshrc文件 最后更新时间 2025-03-17 11:09:34 # 设置日志文件 LOG_FILE="/tmp/ssh_notification_debug.log" # 记录详细日志的函数 log_debug() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [PID:$$] [SSH_TTY:$SSH_TTY] [PPID:$PPID] $1" >> "$LOG_FILE" } # 记录脚本启动 log_debug "脚本开始执行 ====================" log_debug "SSH_CLIENT: $SSH_CLIENT" # 获取登录者的用户名 user=$USER # 获取登录IP地址 ip=${SSH_CLIENT%% *} # 创建基于用户、IP和当前小时的锁文件名 # 这样同一IP同一用户每小时只会通知一次 current_hour=$(date +%Y%m%d%H) LOCK_FILE="/tmp/ssh_notify_${user}_${ip}_${current_hour}" GLOBAL_LOCK="/tmp/ssh_notification.lock" log_debug "检查锁文件: $LOCK_FILE" # 简化的锁定机制,兼容dash shell if [ -f "$LOCK_FILE" ]; then log_debug "本小时已经为用户${user}从IP${ip}发送过通知" echo "Welcome back. The administrator has already been notified of your login this hour." exit 0 fi # 创建锁定文件 touch "$LOCK_FILE" log_debug "已创建锁文件: $LOCK_FILE" # 获取登录的时间 time=$(date +%F%t%k:%M) # 服务器的IP地址和自定义名称 server='204-ray-server-in-mckj' # 修改函数声明语法,使其兼容Dash DingDingalarm() { log_debug "开始发送钉钉通知" local url="https://oapi.dingtalk.com/robot/send?access_token=钉钉token" local UA="Mozilla/5.0(WindowsNT6.2;WOW64)AppleWebKit/535.24(KHTML,likeGecko)Chrome/19.0.1055.1Safari/535.24" local res res=$(curl -XPOST -s -L -H"Content-Type:application/json" -H"charset:utf-8" "$url" -d "{\"msgtype\":\"markdown\",\"markdown\":{\"title\":\"$1\",\"text\":\"$2\"}}") if [ $? -eq 0 ]; then log_debug "钉钉通知发送成功: $res" echo "钉钉通知已发送,结果:$res" echo "Notification sent to admin." else log_debug "钉钉通知发送失败: $res" echo "钉钉通知发送失败,错误信息:$res" fi } # 使用Markdown格式美化通知内容 message="### 🔔 服务器登录通知 🔔\n\n**时间**:<font color='#FF5722'>$time</font>\n\n**服务器**:<font color='#2196F3'>$server</font>\n\n**用户**:<font color='#4CAF50'>$user</font>\n\n**来源IP**:<font color='#9C27B0'>$ip</font>\n\n**会话信息**:TTY=$SSH_TTY, PID=$$, PPID=$PPID\n\n> Please make sure to check if this login is expected." DingDingalarm "服务器登录通知" "$message" # 打印日志,通知管理员并告知操作将被记录 echo "The administrator has been notified. All actions will be logged." log_debug "通知完成,脚本结束 ====================" # 要定期清理锁文件,请使用以下命令设置cron作业(在root权限下执行一次): # echo "5 * * * * root find /tmp -name 'ssh_notify_*' -type f -mmin +60 -delete" > /etc/cron.d/clean_ssh_locks 小插曲 直接 cp 到 sshrc 中时报错 ...

March 13, 2025 · 2 min · 333 words · Ray

服务器初始化

服务器初始化 参考链接 https://www.ruanyifeng.com/blog/2014/03/server_setup.html https://hufangyun.com/2017/linux-init/ 第一篇阮一峰老师的,第二篇胡方运老师的, 主要内容可能与第二篇相似,希望以后我能进行完善,不要太过于臃肿也好。 针对于自己的个人习惯。也记录一个流程,以后配置服务器标准一点 刚购买完服务器要做的操作 这里就忽视安全组的问题了。因为之前买过几年。安全组的配置基本一致,我也不记得初始化啥样子了,如果进不去自己检查网络连接,或者网页进去也行 这里买的是阿里云的 99 一年,2c2g ubuntu24,3M 固定带宽。控制台启动后先重置root密码 然后远程登录 ssh root@ip.ip.ip.ip 进来看着原先的一串主机名眼睛花,改一手主机名 hostnamectl set-hostname <new-hostname> 然后重新登录就行了。 如果只是要改命令行提示符一串可以研究~/.bashrc和各种插件,关于美化命令行那也是水很深,我就喜欢傻黑粗的玩意儿 新账号 操作 Linux 系统任何时候尽量不使用 root 账户,毕竟权限太大对小白不是好事,有自知之明且要学一下好习惯,创建一个管理员账户 [[Linux-用户管理#新建用户]] 这里基本和文章开头贴的博客一致。我也创建admin用户组 addgroup admin 添加新用户(ray) useradd -d /home/ray -s /bin/bash -m ray 上面命令中,参数 d 指定用户的主目录,参数 s 指定用户的 shell,参数 m 表示如果该目录不存在,则创建该目录。 接着,设置新用户的密码。 passwd ray 将新用户(ray)添加到用户组(admin)。 usermod -a -G admin ray 接着,为新用户设定sudo权限。 sudo vim /etc/sudoers 找到下面这一行。 root ALL=(ALL:ALL) ALL 在这一行的下面,再添加一行。 1 2 root ALL=(ALL:ALL) ALL ray ALL=(ALL:ALL) ALL 验证 ...

March 12, 2025 · 2 min · 269 words · Ray