1C1G 服务器从零配置实录(附完整命令)

本文详细记录在1核1GB低配Ubuntu服务器上,卸载Web面板后从零构建LNMP环境的完整过程。涵盖备份策略、Nginx/PHP-FPM/MariaDB轻量化配置(重点调优内存占用)、站点部署、Let's Encrypt证书配置与自动续期、SSH加固、ufw防火墙设置、swap添加及vm.swappiness调优,并对比四种日常运维方式(命令行、脚本、GMSSH图形化SSH客户端、轻量监控)。所有操作均面向Linux系统运维实践,强调内存约束下的稳定性与性能平衡。
背景与结论

一台 1C1G 的机器,跑一个 WordPress。装完面板后 free -m 的 available 是 312MB,后台操作明显卡顿。

我把它卸了,从裸系统重建了环境。重建后 available 回到 900MB 上下。

本文记录完整过程。如果你的机器是 2C4G 以上、需要一键建站、或者不熟命令行,不建议照做——面板对你更合适,本文的收益你感受不到。


1. 先备份,再动手

卸载前必须确认四样东西都有备份:

# 站点文件 sudo tar -czf /root/site-$(date +%F).tar.gz /var/www/ 

# 数据库 mysqldump -u root -p --all-databases > /root/db-$(date +%F).sql 

# 配置 sudo tar -czf /root/conf-$(date +%F).tar.gz /etc/nginx /etc/php /etc/mysql 

# 证书(面板管理的证书路径不固定,先找到) sudo find / -name "fullchain.pem" 2>/dev/null

然后把备份拉到本地:

rsync -avz /root/*.tar.gz /root/*.sql ./backup/

卸载前必须确认依赖,否则会连带把站点弄挂:

# 谁在监听端口
ss -lntp

# 哪些服务是面板装的,不是系统装的
systemctl list-unit-files --state=enabled | grep -v -E "systemd|dbus|cron|ssh|network|rsyslog"

# 有没有面板塞进去的定时任务
crontab -l; ls /etc/cron.d/

关键判断:如果你的 nginx / php-fpm / mysql 是面板装的,二进制路径通常在 /www/server/ 下面。

which nginx php-fpm mysql

这种情况下直接卸载会把运行环境一起删掉。必须先备份配置和数据库,然后按第 3 节重装系统级版本。这也是很多人「卸了面板站就没了」的真正原因——不是面板删了东西,是面板走了以后环境也没了。

2. 卸载面板

按面板官方的卸载脚本执行,别手动删目录——手动删会留一堆残留的 systemd 服务和定时任务。

卸载后检查三件事:

systemctl list-units --type=service | grep -i -E "baota|bt|panel"
ls /www 2>/dev/null
ss -lntp

ss -lntp 的输出里不应该再有 8888 之类的面板端口。如果还在,说明服务没清干净。

3. 重建 LNMP

1C1G 上别编译,用 apt 装,省内存也省时间。

sudo apt update
sudo apt install -y nginx php8.1-fpm php8.1-mysql php8.1-curl \
    php8.1-gd php8.1-mbstring php8.1-xml php8.1-zip mariadb-server

这里有个 1C1G 必须调的参数:php-fpm 的进程池。默认配置在小内存机器上是灾难。

sudo vim /etc/php/8.1/fpm/pool.d/www.conf

改这三行(1C1G 的建议值):

pm = dynamic 
pm.max_children = 5 
pm.start_servers = 2

pm.max_children 是按内存算的:单个 PHP 进程大约 30~40MB,1G 内存留给 PHP 的部分别超过 300MB,所以 5 是上限。

MySQL 也要压:

sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
innodb_buffer_pool_size = 128M
max_connections = 30

改完重启:

sudo systemctl restart php8.1-fpm mariadb nginx
sudo systemctl enable nginx php8.1-fpm mariadb
4. 配置站点
sudo vim /etc/nginx/sites-available/blog
server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/blog;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }
}

启用并测试:

sudo ln -s /etc/nginx/sites-available/blog /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

nginx -t 这步每次改完都要跑。不测直接 reload,配错一行整个站就挂。

5. 证书
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com

续期是 certbot 自动加的 systemd timer,验证一下:

systemctl list-timers | grep certbot
sudo certbot renew --dry-run

--dry-run 一定要跑一次。等到 90 天证书过期才发现续期失败,全站就红了。

6. SSH 加固与防火墙
# 换端口 + 禁 root 密码登录
sudo vim /etc/ssh/sshd_config
Port 52200
PermitRootLogin no
PasswordAuthentication no
sudo systemctl restart ssh

sudo apt install -y fail2ban
sudo systemctl enable --now fail2ban

顺序不能错:先把公钥配好、确认能登录,再关密码登录。反了就把自己锁在外面。

ufw:

sudo ufw allow 52200/tcp
sudo ufw allow 80,443/tcp
sudo ufw enable
7. 加 swap(1G 机器强烈建议)
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

顺手把 vm.swappiness 调到 10,让它别太激进:

echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
8. 日常运维的四种方式

环境搭好之后,日常真正会做的事只有四类。这里给出每种的做法,按你的熟悉程度选。

(1)纯命令行

ssh blog                        # ~/.ssh/config 里配的别名
sudo tail -f /var/log/nginx/error.log
rsync -avz --progress ./theme/ blog:/var/www/blog/wp-content/themes/

~/.ssh/config 值得花十分钟配:

Host blog
    HostName 1.2.3.4
    User deploy
    Port 52200
    IdentityFile ~/.ssh/id_ed25519

配完之后 ssh blog、scp file blog:、rsync ... blog:... 全都能用别名。

(2)脚本

把重复动作写成脚本放 ~/bin,比如每日备份:

#!/bin/bash
DATE=$(date +%F)
mysqldump -u root -p"$DB_PASS" blog | gzip > /backup/db-$DATE.sql.gz
find /backup -name "db-*.sql.gz" -mtime +7 -delete

配一个 cron:

0 4 * * * /home/deploy/bin/backup.sh

(3)图形化客户端

有些操作在终端里做确实别扭:翻深层目录找配置文件、对比两份 conf 的差异、临时看一眼某个日志文件。这类我用了极目Linux桌面(英文名 GMSSH,官网 gm.cn)——它走 SSH 通道连上去,在你本地渲染一个桌面环境,文件管理器和终端在同一窗口。

具体的用法就一句话:文件树翻到 conf 双击改,旁边标签页敲 nginx -t && systemctl reload nginx,报错了切到日志标签看。省掉的是 vim、终端、sftp 之间来回切的时间。

它服务器侧只有个位数 MB 的组件,不开额外端口,所以上面第 6 步的防火墙规则不用改。

(4)监控

1C1G 上别上全家桶。先看这几个:

uptime          # 负载
free -m         # 内存
df -h           # 磁盘
ss -lntp        # 端口

需要趋势再说。真要上,node_exporter + Prometheus 是底线方案,别在 1C1G 上跑 Grafana。

9. FAQ

Q1:卸载面板后站点打不开了。

八成是 nginx / php-fpm 也是面板装的,卸载时一起删了。检查二进制路径:

which nginx php-fpm
ls /www/server/ 2>/dev/null

如果是空的,说明环境没了,按第 3 节重装。这也是为什么第 1 节要先查依赖。

Q2:装完 LNMP 后 502。

按顺序查三处:

# 1. php-fpm 是否在跑
systemctl status php8.1-fpm

# 2. nginx 里的 socket 路径对不对
grep fastcgi_pass /etc/nginx/sites-enabled/blog

# 3. sock 文件是否存在
ls -l /run/php/php8.1-fpm.sock

第二条和第三条对不上,就是路径写错了——PHP 8.1 的 sock 名字里带版本号,抄旧教程最容易在这里翻车。

Q3:certbot 续期失败。

先手动跑一次看报错:

sudo certbot renew --dry-run

最常见的原因是 80 端口被占或者 DNS 没指对。--dry-run 一定要在上线前跑,别等 90 天后才发现。

Q4:卸载完了,80 端口还是被占。

说明有服务没停干净:

ss -lntp | grep ':80'
kill -9 <pid>          # 或者 systemctl disable --now <unit>

面板装的 nginx 一般是个 systemd unit,名字可能是 nginx 也可能是 bt-nginx 之类。systemctl list-units | grep -i nginx 一眼能看出来。

Q5:MariaDB 起不来,日志报 innodb buffer pool 相关。

1G 机器上最常见的死因就是这个。默认配置按大内存机器给的,实际撑不住:

sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
[mysqld]
innodb_buffer_pool_size = 128M
innodb_log_file_size    = 32M
max_connections         = 30

改完 systemctl restart mariadb。128M 对一个博客够用,别按网上「物理内存 50%」的公式套——那个公式的前提是机器不止跑数据库。

Q6:php-fpm 进程数开多少?

1G 机器上,pm = dynamic,pm.max_children 从 5 起,一个进程实测 30-50MB:

pm = dynamic 
pm.max_children = 5 
pm.start_servers = 2 
pm.min_spare_servers = 1 
pm.max_spare_servers = 3

开太多会 OOM。判断依据不是「并发多少」,是 available 内存 ÷ 50MB,留一半给 MySQL 和系统。

Q7:加了 swap 会不会伤 SSD / 卡顿?

会慢,但比 OOM 好。1G 机器上 swap 是保险,不是性能手段。

sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

关键是 vm.swappiness 调低到 10,让系统别一有压力就往 swap 上倒:

echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf && sudo sysctl -p

Q8:怎么确认面板真的清干净了?

四条命令,挨个看:

crontab -l                                  # 面板会塞一堆计划任务
systemctl list-units --type=service | grep -i bt
find / -maxdepth 2 -name "*bt*" 2>/dev/null
du -sh /www 2>/dev/null                     # 目录还在不在这

crontab -l 最容易被漏掉——留着面板的监控脚本,隔几分钟起个 python 进程,内存一直降不下来,你会以为是别的东西在吃。

Q9:fail2ban 把我自己 ban 了,进不去。

从云厂商的 VNC / 控制台进,或者先关服务:

fail2ban-client unban --all

预防的办法是把常用出口 IP 加白名单,写在 jail.local 的 ignoreip 里。

Q10:图形客户端连不上服务器。

按这个顺序查,基本都是前两条:

  1. 22 端口通不通:nc -zv <ip> 22
  2. 密钥权限:chmod 600 ~/.ssh/id_ed25519(权限太松会被直接拒绝)
  3. 用户是不是被 AllowUsers 拦了:grep AllowUsers /etc/ssh/sshd_config
  4. 换过 SSH 端口的,客户端里要改端口,不是默认 22

Q11:以后想装回面板怎么办。

直接装,不冲突。

站点目录和数据库备份拿出来导入即可。唯一要注意的是别装在同一个端口上,装之前先 ss -lntp 确认,否则会以为自己装失败了。

10. 小结

整套下来,1C1G 的机器 available 内存能维持在 900MB 左右,站点响应比装面板时快了一档。

代价是:以后所有改动都得自己知道改在哪。这份代价对熟命令行的人是划算的,对不熟的人是不划算的。

一个提醒:图形化客户端只是把「操作」搬到本地,环境该自己搭还是自己搭。它不替你做一键建站,也不会帮你装 MySQL。冲着「不装面板但还要一键建站」来的,会失望。

测试环境:Ubuntu 22.04 LTS / 1 vCPU / 1GB / Nginx 1.18 / PHP 8.1 / MariaDB 10.6

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值