Debian Server

关于我如何搭建自己的服务器,实现自己想要的功能的一篇帖子。

Posted by Ryan Yim on 2020-12-03
Estimated Reading Time 121 Minutes
Words 24.9k In Total
Viewed Times

服务器

我的服务器是跟Vultr 买的,服务器座标海外。为什么不买国内的呢?因为Github下载东西很慢,所以买了服务器,其中一个功能当然是帮我下载Github的大文件啦。另外还有一个原因是,便宜。

服务器怎么买呢?对我来说,便宜+老牌就行了。国外的主机可以快乐访问国内速度慢的资源,这很舒服,比如我都不用修改Debian官方源镜像,还有Github克隆仓库也快多了。但国外主机也有个问题:网络不稳定,高峰期SSH都能给我掉线……延时有点高。

我的服务器快速部署脚本「仅限Debian」

仓库:https://github.com/rmshadows/rm_scripts

脚本部署完成事项(截至2022-04):

  • 检查点一:
    • 更改镜像(针对国内服务器);
    • 默认源安装apt-transport-https ca-certificates wget gnupg2 gnupg lsb-release(必选);
    • 配置unattended-upgrades
  • 检查点二:
    • 安装sudo openssh-server zsh(必选);
    • 设置所有用户使用zsh;
    • 新建用户(包括配置sudo、是否使用zshrc、sudo免密码)
  • 检查点三:
    • 安装vim-full,卸载vim-tiny;
    • 添加/usr/sbin到环境变量;
      • 添加添加HOME目录文件夹(Data for data;Applications for apps;Temp for file transport;Workplace for work;Services for service)(必选);
    • 安装bash-completion;
    • 安装zsh-autosuggestions
  • 检查点四:
    • 自定义自己的服务(运行一个shell脚本);
    • 设置主机名
    • 配置语言
    • 配置时区
    • 配置tty1自动登录
  • 检查点五:
    • 从apt仓库拉取常用软件
    • 安装Python3
    • 安装Git
    • 安装OpenSSH
    • 安装nodejs
    • 安装npm
  • 检查点六:
    • 安装、配置HTTP服务
  • 检查点七:
    • 安装docker-ce
  • 检查点八:
    • 安装ufw防火墙(默认开放22、80 、443)

服务器域名、SSL证书购买

域名呢,当然有免费的,比如Freenom。我个人呢是跟阿里巴巴买的,我买的最便宜的,花了我一块钱,续费价格是13元/年。只要你选的域名越冷门,价格就越低,记得关注续费价格。

SSL证书有很多,COMODOLet‘s Encrypt,有免费的也有付费的。我买的当然是免费的,不过我是通过阿里中介买的,一年有效期。

服务器应用

Apache2

Debian的Apache2配置和其他发行版有所不同。这个在Apache2文档中有说明,这里我随意翻译了下:

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
Contents - 目录
========
Apache2 Configuration under Debian GNU/Linux - Apache2在Debian下的配置
Files and Directories in '/etc/apache2' - 在/etc/apache2目录中的配置文件
Tools - 工具
Using mod_cache_disk - 使用mod_cache_disk
SSL - SSL
Enabling SSL - 开启SSL
Creating self-signed certificates - 生成自签名的证书
SSL workaround for MSIE - SSL & MSIE
Suexec - 关于suEXEC
Documentation - 文档
Upgrades - 升级
Common Problems - 常见问题
For Developers - 开发者指南

Apache2 Configuration under Debian GNU/Linux - Apache2在Debian下的配置
============================================

Debian's default Apache2 installation attempts to make adding and
removing modules, virtual hosts, and extra configuration directives as
flexible as possible, in order to make automating the changes and
administering the server as easy as possible.

Debian中的Apache2默认部署方式将尽可能地让添减模块、虚拟主机和配置指令更加灵活,让管理员能够以更简洁明了、自动化的方式来管理服务器。

Please be aware that this layout is quite different from the standard
Apache configuration. Due to the use of environment variables, apache2
needs to be started/stopped with '/etc/init.d/apache2', apachectl, or
apache2ctl. Calling '/usr/bin/apache2' directly will not work with the
default configuration. To call apache2 with specific command line
arguments, just call apache2ctl with the same arguments.

请注意,Debian上的Apache2配置文件布局与标准配置完全不同。由于使用了环境变量,apache2需要使用“/etc/init.d/apache2”、apachectl或apache2ctl启动/停止。直接调用'/usr/bin/apache2'将无法使用默认配置。如果要调用apache2,只需使用调用apache2ctl时所用的参数。

Files and Directories in '/etc/apache2':
在/etc/apache2中的文件:
---------------------------------------

apache2.conf

This is the main configuration file. It does not include any
actual configuration we expect to be adapted on your site, so
where possible please do not touch it. This file is the
foundation stone of the Apache configuration in Debian and should
be up to date after upgrades to make sure all configuration pieces
are properly included.

这是主配置文件。它不包括任何我们希望在您的站点上调整实际配置,所以如果可能,请不要碰它。这个文件是
Debian中Apache配置的基石。更新软件后请手动检查这个文件,以确保所有配置件包括在内。

If you want to extend the global configuration, you can customize
the Apache web server by including configuration files through the
conf-available mechanism. To change listening ports and socket
configuration use ports.conf (see below).

如果要扩展全局配置,可以自定义通过配置可用机制。更改侦听端口和套接字配置使用ports.conf(见下文)。

ports.conf

Configuration directives for which ports and IP addresses to
listen to.

端口和IP地址的监听配置指令。

magic

Patterns for mod_mime_magic. This is not compatible with the format
used by current versions of the file/libmagic packages.

mod_mime_magic的样式。这与当前版本的file/libmagic包使用的格式不兼容。

envvars

This contains environment variables that may be used in the
configuration. Some settings, like user and pid file, need to
go in here so that other scripts can use them. It can also
be used to change some default settings used by apache2ctl,
including the ulimit value for the maximum number of open files.
The default LANG=C setting is also here, and can be changed to a
different language.

这里包含可以在中使用的环境变量配置。一些设置,如用户和pid文件,需要进入这里以便其他脚本可以使用它们。它也可以用于更改apache2ctl使用的某些默认设置,包括最大打开文件数的ulimit值。默认的LANG=C设置也在这里,可以更改为不同的语言。

conf-available/

Files in this directory are included in the global server scope by
this line in apache2.conf:

此目录中的文件包含在全局服务器作用域中,被定义在apache2.conf配置文件中的这一行:

# Include generic snippets of statements
IncludeOptional conf-enabled/*.conf

This is a good place to add additional configuration
directives. All configuration snippets need a '.conf' suffix to be
included as actual configuration. The local administrator should
use file names starting with 'local-' to avoid name clashes with
files installed by packages.

这是添加附加配置的好地方指令。所有配置片段都需要“.conf”后缀包括在实际配置中。本地管理员应该
使用以“local-”开头的文件名以避免与由程序包安装的文件。

Configuration snippets can be enabled and disabled by using the
a2enconf and a2disconf executables. This works similarly to the
approach used for modules and sites below.

可以使用a2enconf和a2discof可执行文件。这与用于以下模块和站点的方法。

Configuration snippets can of course also be included in individual
virtual hosts.

配置片段当然也可以包含在虚拟主机。

conf-enabled/

Like mods-enabled/ and sites-enabled/, a piece of configuration is
enabled by symlinking a file from conf-available/ into this
directory. The a2enconf helper is provided to assist this task.

与mods enabled/和sites enabled/一样,一个配置是通过将文件从conf available/符号链接到
目录。提供a2enconf帮助程序来协助此任务。

mods-available/

This directory contains a series of .load and .conf files.
The .load files contain the Apache configuration directive
necessary to load the module in question. The corresponding
.conf files contain configuration directives necessary to
utilize the module in question.

这个目录包含一系列.load和.conf文件。.load文件包含Apache配置指令需要加载有问题的模块。相应的.conf文件包含使用相关模块所需的配置指令。

mods-enabled/

To actually enable a module for Apache2, it is necessary to
create a symlink in this directory to the .load (and .conf, if
it exists) files associated with the module in
mods-available/. For example:

要真正启用Apache2的模块,必须在这个目录中创建一个指向.load(和.conf,如果它存在)与中的模块关联的文件可用mods/。例如:

cgi.load -> /etc/apache2/mods-available/cgi.load

The a2enmod helper can be used to enable a module.

a2enmod可用于启用模块。

sites-available/

Like mods-available/, except that it contains configuration
directives for different virtual hosts that might be used with
apache2. Note that the hostname doesn't have to correspond
exactly with the filename. '000-default.conf' is the default
host which is provided by Debian.

就像mods available/,它只包含可能一起使用的不同虚拟主机的指令Apache2配置。请注意,主机名不必对应和文件名一模一样。000-default.conf是由Debian提供的默认主机。

sites-enabled/

Similar in functionality to mods-enabled/, sites-enabled
contains symlinks to sites in sites-available/ that the
administrator wishes to enable.

功能类似于mods enabled/,sites enabled包含指向管理员希望启用的可用站点中站点的符号链接。

Apache uses the first VirtualHost that matches the IP/Port
as default for named virtual hosts. Therefore the 'default'
site should be called '000-default' to make sure it sorts before
other sites.

Apache使用第一个与IP/端口匹配的虚拟主机作为命名虚拟主机的默认值。因此“default”站点应该被称为'000-default',以确保它排在在其他网站之前。

Example:
dedasys.conf -> /etc/apache2/sites-available/dedasys.conf

The a2ensite helper can be used to enable a site.

a2ensite可用于启用站点。

The Include directives ignore files with names that do not end with a
.conf suffix. This behavior has changed from previous releases!

Include指令将忽略不以.conf后缀的文件。此行为与以前的版本不同!

In some cases you may want to enable a specific piece of configuration
(think of files shipped in conf-available/) for a particular virtual
host only and not globally as is our default. In such cases you can
disable the configuration at a global scope for example by doing

在某些情况下,您可能希望启用特定的配置(想想conf available/中提供的文件)对于特定仅主机的虚拟机
,而不是我们默认的全局主机。在这种情况下,你可以在全局范围禁用配置,例如通过

a2disconf some-configuration

Then it can be included in a particular virtual host within a file in
sites-enabled/. You may want to add

然后它可以包含在文件中的特定虚拟主机中站点已启用/。您可能需要添加

Include conf-available/some-configuration.conf

in that site configuration. However, be careful, as this may not work for
some configurations, depending on the context and implications of some
directives.

到那个站点配置中。但是,请小心,因为这可能不适用于一些配置,取决于某些配置的上下文和含义
指令。

Tools - 工具
-----

a2enmod and a2dismod are available for enabling and disabling modules utilizing
the above configuration system.

a2enmod和a2dismod可用于启用和禁用模块配置系统。

a2ensite and a2dissite do essentially the same thing as the above tools, but
for sites rather than modules. Finally a2enconf and a2disconf are the
corresponding tools for configuration snippets.

a2ensite和a2disite所做的基本上与上个工具相同,但是对于站点而不是模块。最后,a2enconf和a2discof是
配置片段的相应工具。

a2query is a helper script providing runtime information about the running
server instance. For example it can be used to query enabled modules, the
selected MPM, and other information. This tool is primarily meant for package
maintainers who need to interact with the Apache packages to activate
their configurations upon package installation, but it can be used by users
as well.

a2query是一个助手脚本,提供有关服务器实例。例如,它可以用于查询启用的模块选择MPM和其他信息。此工具主要用于打包需要与Apache包交互才能激活的维护人员它们的配置在包安装时,但用户也可以使用它。

apxs2 -a/-A is modified to use a2enmod to activate newly installed modules.

apxs2-a/-A 被修改为使用a2enmod来激活新安装的模块。

Using mod_cache_disk - 磁盘缓存
====================

To ensure that the disk cache does not grow indefinitely, htcacheclean is
started when mod_cache_disk is enabled. Both daemon and cron (daily) mode
are supported. The configuration (run mode, cache size, etc.) is in
'/etc/default/apache2'.

为了确保磁盘缓存不会无限期增长,htcacheclean将在启用mod_cache_disk时同时启动。守护程序和cron(每日)模式支持。在“/etc/default/apache2”可以配置(运行模式、缓存大小等)。

Normally, htcacheclean is automatically started and stopped by
'/etc/init.d/apache2'. However, if you change the state of mod_cache_disk or
the configuration of htcacheclean while apache2 is running, you may need to
manually start/stop htcacheclean with "/etc/init.d/apache2 start-htcacheclean"
or "/etc/init.d/apache2 stop-htcacheclean".

通常,htcacheclean和'/etc/init.d/apache2'一起自动启动和停止。但是,如果您更改mod_cache_磁盘的状态或在apache2运行时htcacheclean的配置,您可能需要使用“/etc/init.d/apache2 start htcacheclean”或“/etc/init.d/apache2 stop htcacheclean”手动启动/停止htcacheclean。

Note that mod_cache_disk was named mod_disk_cache in versions 2.2 and earlier.

请注意,在2.2及更早版本中,mod_cache_disk被命名为mod_disk_cache。

SSL - SSL
===

Enabling SSL - 启用SSL
------------

To enable SSL, type (as user root):

a2ensite default-ssl
a2enmod ssl

使用a2ensite default-ssl 和 a2enmod ssl启用ssl,两个都要运行。

If you want to use self-signed certificates, you should install the ssl-cert
package (see below). Otherwise, just adjust the SSLCertificateKeyFile and
SSLCertificateFile directives in '/etc/apache2/sites-available/default-ssl.conf'
to point to your SSL certificate. Then restart apache:

如果要使用自签名证书,则应安装ssl-sert包(见下文)。否则,只需调整'/etc/apache2/sites available/default-ssl.conf中的sslcertificateKey和SSLCertificateFile参数指向SSL证书。然后重新启动apache:

service apache2 restart

The SSL key file should only be readable by root; the certificate file may be
globally readable. These files are read by the Apache parent process which runs
as root, and it is therefore not necessary to make the files readable by the
www-data user.

SSL密钥文件应该只能由root用户读取;证书文件可以是全局可读。这些文件由以root用户运行的Apache父进程读取
因此,不必让www-data用户可读。

Creating self-signed certificates - 创建自签名证书
---------------------------------

If you install the ssl-cert package, a self-signed certificate will be
automatically created using the hostname currently configured on your computer.
You can recreate that certificate (e.g. after you have changed '/etc/hosts' or
DNS to give the correct hostname) as user root with:

如果安装ssl-cert包,则自签名证书将使用计算机上当前配置的主机名自动创建。您可以以root用户重新创建该证书(例如,在更改“/etc/hosts”或DNS提供正确的主机名):

make-ssl-cert generate-default-snakeoil --force-overwrite

To create more certificates with different host names, you can use

要使用不同的主机名创建更多证书,可以使用

make-ssl-cert /usr/share/ssl-cert/ssleay.cnf /path/to/cert-file.crt

This will ask you for the hostname and place both SSL key and certificate in
the file '/path/to/cert-file.crt'. Use this file with the SSLCertificateFile
directive in the Apache config (you don't need the SSLCertificateKeyFile in
this case as it also contains the key). The file '/path/to/cert-file.crt'
should only be readable by root. A good directory to use for the additional
certificates/keys is '/etc/ssl/private'.

这将要求您输入主机名、SSL密钥和证书存放路径。将此文件与SSLCertificateFile参数配合使用时就不需要在ssekficate中指定密钥路径了)。证书文件'/path/to/cert-文件.crt'应该只能由根用户读取。'/etc/ssl/private'会时一个存储新增的证书/密钥好地方。

SSL workaround for MSIE - MSIE下的SSL
-----------------------

The SSL workaround for MS Internet Explorer needs to be added to your SSL
VirtualHost section (it was previously in ssl.conf but caused keepalive to be
disabled even for non-SSL connections):

MS Internet Explorer(IE浏览器)的SSL解决方案需要添加到SSL中虚拟主机部分(在以前的ssl.conf中,会引起keepalive在非SSL连接下被禁用):

BrowserMatch "MSIE [2-6]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown

The default SSL virtual host in '/etc/apache2/sites-available/default-ssl.conf'
already contains this workaround.

现在/etc/apache2/sites_available/default-ssl.conf中的默认SSL虚拟主机已包含此解决方法。

Suexec
======

Debian ships two version of the suexec helper program required by
mod_suexec. It is not installed by default, to avoid possible security
issues. The package apache2-suexec-pristine contains the standard version
that works only with document root /var/www, userdir suffix public_html,
and Apache run user www-data. The package apache2-suexec-custom contains a
customizable version that can be configured with a config file to use
different settings (like /srv/www as document root). For more information
see the suexec(8) man page in the apache2-suexec-custom package.

Debian提供了mod_suexec所需的两个版本suexec。默认情况下不安装,以避免可能的安全性问题。apache2 suexec pristine包包含标准版本它只适用于文档root/var/www,userdir后缀public_html,Apache运行用户www数据。apache2 suexec定制包包含可自定义版本,可配置为使用配置文件不同的设置(如/srv/www作为文档根目录)。了解更多信息请参阅apache2suexec定制包中的suexec(8)手册页。

Since apache2-suexec-custom has received less testing and might be slightly
slower, apache2-suexec is the recommended version unless you need the features
from apache2-suexec-custom.

由于Apache2-suexec-custom测试得不多,所以Apache2-suexec才是推荐的版本,除非您需要这些来自apache2 suexec_custom特性。

Starting with Apache 2.4 both alternatives can be installed at the same
time and the default suexec mechanism can be picked by using the
update-alternatives(8) system.

从Apache2.4开始,同时安装两个备选方案可以同时安装,然后在从偏好方案update-alternatives(8)系统中选择。

Unicode File Name Normalization - Unicode文件名规范化
===============================

Using Apache with the document root on a file system that does unicode
normalization on the filenames can cause security issues. In Debian,
this affects ZFS with the non-default option to enable filename normalization,
and HFS+. It is strongly recommended not to use Apache with such file systems.
More information about this issue can be found by searching the web for
CVE-2013-0966.

在执行unicode的文件系统上使用带有文档根目录的Apache文件名的规范化可能会导致安全问题。在Debian,这会通过启用文件名规范化的非默认选项影响ZFS,和HFS+。强烈建议不要在此类文件系统中使用Apache。有关此问题的详细信息,请在web上搜索CVE-2013-0966。

Documentation - 文档
=============

The full Apache 2 documentation can be found on the web at

完整的文档在:

http://httpd.apache.org/docs/2.4/

or, if you have installed the apache2-doc package, in

或者本地文档:

/usr/share/doc/apache2-doc/manual/

or at

http://localhost/manual/

There is also a wiki that contains useful information:

这里还有更多信息:

http://wiki.apache.org/httpd/

Some hints about securing Apache 2 on Debian are available at

有关在Debian上保护Apache2的一些提示,请访问:

http://wiki.debian.org/Apache/Hardening

Upgrades - 升级
========

Changes in the Apache packages that require manual configuration adjustments
are announced in NEWS.Debian. Installing the apt-listchanges package is
recommended. It will display the relevant NEWS.Debian sections before
upgrades.

Apache软件包中需要手动调整配置的更改发布于NEWS.Debian. 安装apt listchanges包是推荐。升级之前它将显示相关NEWS.Debian。

Multiple instances - 多实例
==================

There is some support for running multiple instances of Apache2 on the same
machine. See '/usr/share/doc/apache2/README.multiple-instances' for more
information.

有一些在同一个平台上运行多个Apache2实例机器的帮助。参见'/usr/share/doc/apache2/自述文件.multiple-实例了解更多信息。

Common Problems - 常见问题
===============

1) Error message "Could not reliably determine the server's fully qualified
domain name, using 127.0.0.1 for ServerName" during start

错误消息“无法可靠地确定服务器的完全限定域名,在启动期间对ServerName使用127.0.0.1

This can usually be ignored but it means that Apache httpd was unable to obtain
a fully-qualified hostname by doing a reverse lookup on your server's IP
address. You may want to add the fully-qualified hostname to '/etc/hosts'.
An alternative is to specify "ServerName 127.0.0.1" in the global server
context of the configuration, e.g. in
'/etc/apache2/conf-enabled/local-servername.conf'.

这通常可以忽略,但这意味着apachehttpd无法获得通过对服务器的IP进行反向查找来获得完全限定的主机名
地址。您可能希望将完全限定的主机名添加到“/etc/hosts”。另一种方法是在全局服务器中指定“ServerName 127.0.0.1”
例如'/etc/apache2/conf-enabled/local-servername.conf'.

2) Error message "mod_rewrite: could not create rewrite_log_lock"

错误消息“mod_rewrite:无法创建重写日志锁”

This probably means that there are some stale SYSV semaphores around. This
usually happens after apache2 has been killed with kill -9 (SIGKILL). You can
clean up the semaphores with:

这可能意味着周围有一些过时的SYSV信号量。这个通常发生在apache2被kill-9(SIGKILL)杀死之后。你可以
使用以下命令清除信号量:

ipcs -s | grep www-data | awk ' { print $2 } ' | xargs ipcrm sem

3) Message "File does not exist: /etc/apache2/htdocs" in error log

错误日志中的消息“文件不存在:/etc/apache2/htdocs”

In most cases this means that no matching VirtualHost definition could be
found for an incoming request. Check that the target IP address/port and the
name in the Host: header of the request actually match one of the virtual
hosts.

在大多数情况下,这意味着没有匹配的VirtualHost定义为传入请求找到。检查目标IP地址/端口和主机中的名称:请求的头实际上与虚拟主人。

4) Message "Couldn't create pollset in child; check user or system limits" in
error log

错误日志中的消息“无法在子级中创建pollset;请检查用户或系统限制”

On Linux kernels since 2.6.27.8, the value in

在2.6.27.8以后的Linux内核上

/proc/sys/fs/epoll/max_user_instances

needs to be larger than

需要大于

for prefork/itk MPM: 2 * MaxClients
for worker/event MPM: MaxClients + MaxClients/ThreadsPerChild

It can be set on boot by adding a line like

它可以通过添加一行:

fs.epoll.max_user_instances=1024

to '/etc/sysctl.conf'.

到'/etc/sysctl.conf'.

There are several other error messages related to creating a pollset that can
appear for the same reason.

还有几个与创建pollset相关的错误消息可以因为同样的原因出现。

On the other hand, errors about adding to a pollset are related to the setting
fs.epoll.max_user_watches. On most systems, max_user_watches should be high
enough by default.

另一方面,关于添加到pollset的错误与设置有关fs.epoll.max_user_watches. 在大多数系统上,max_user_watches 默认情况应该足够高了。

5) Message "Server should be SSL-aware but has no certificate configured" in
error log

错误日志中的消息“服务器应支持SSL,但未配置证书”

Since 2.2.12, Apache is stricter about certain misconfigurations concerning
name based SSL virtual hosts. See NEWS.Debian.gz for more details.

从2.2.12开始,Apache对基于名称的SSL虚拟主机以下错误配置的要求更严格,查看NEWS.Debian.gz了解更多细节。

6) Apache does not pass Authorization header to CGI scripts

Apache不向CGI脚本传递授权头。

This is intentional to avoid security holes. If you really want to change it,
you can use mod_rewrite:

这是为了避免安全漏洞。如果你真的想改变它,您可以使用mod_rewrite:

RewriteCond %{HTTP:Authorization} (.*)
RewriteRule . - [env=HTTP_AUTHORIZATION:%1]

7) mod_dav is behaving strangely

mod_dav行为很奇怪

In general, if you use mod_dav_fs, you need to disable multiviews and script
execution for that directory. For example:

通常,如果使用mod_dav_fs,则需要禁用该目录的多视图和脚本执行。例如:

<Directory /var/www/dav>
Dav on
Options -MultiViews -ExecCGI
SetHandler none
<IfModule mod_php5.c>
php_admin_value engine Off
</IfModule>
</Directory>

8) Message "apache2: bad user name ${APACHE_RUN_USER}" when starting apache2
directly

当直接启动apache2时,消息“apache2:bad user name${APACHE_RUN_user}”

Use apache2ctl (it accepts all the same options as apache2).

请改用apache2ctl

9) A PUT with mod_dav_fs fails with "Unable to PUT new contents for /...
[403, #0]" even if Apache has permission to write the file.

带有mod_dav_fs的PUT失败,并显示“无法为/….放入新内容”[403,#0]“即使Apache有写入文件的权限。

Apache also needs write permission to the directory containing the file, in
order to replace it atomically.

Apache还需要权限来替换包含它的目录。

10) When starting/reloading Apache, there is the error message
"ulimit: open files: cannot modify limit: Operation not permitted"

启动/重新加载Apache时,会出现错误消息“ulimit:open files:cannot modify limit:Operation not allowed”

If you are running Apache in a vserver environment, the start script may not
be allowed to set the maximum number of open files. You should adjust
APACHE_ULIMIT_MAX_FILES in /etc/apache2/envvars to your setup. You can
disable changing the limits by setting APACHE_ULIMIT_MAX_FILES=true .

如果在vserver环境中运行Apache,则可能不允许start脚本设置打开文件的最大数量。您应该将/etc/apache2/envvars中的APACHE_ULIMIT_MAX_文件调整为您的设置。您可以通过设置APACHE_ULIMIT_MAX_FILES=true来禁用更改限制。

For Developers - 开发者
==============

The Apache 2 web server package provides several helpers to assist
packagers to interact with the web server for both, build and installation
time. Please refer to the PACKAGING file in the apache2 package for
detailed information.

Apache2Web服务器包提供了几个帮助程序,以帮助打包程序在构建和安装期间与web服务器进行交互。有关详细信息,请参阅apache2包中的打包文件。

配置SSL

证书文件预备:

  • 证书文件:以.crt为后缀或文件类型。
  • 证书链文件:以.crt为后缀或文件类型。
  • 密钥文件:以.key为后缀或文件类型。

Debian 配置指南

  1. 打开终端执行a2enmod ssl

  2. /etc/apache2/sites-available中会有一个配置文件:default-ssl.conf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    自行设置DocumentRoot参数
    添加:
    SSLEngine on
    # 添加SSL协议支持协议,去掉不安全的协议。
    SSLProtocol all -SSLv2 -SSLv3
    # 修改加密套件。
    SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM
    SSLHonorCipherOrder on
    # 将domain name1_public.crt替换成您证书文件名。
    SSLCertificateFile public.crt
    # 将domain name1.key替换成您证书的密钥文件名。
    SSLCertificateKeyFile .key
    # 将domain name1_chain.crt替换成您证书的密钥文件名;证书链开头如果有#字符,请删除。
    SSLCertificateChainFile chain.crt
  3. 然后a2ensite default-ssl.conf

  4. 重启Apache2.

  5. 配置强制跳转HTTPS:a2enmod rewrite。然后在80的000-default的HTTP配置文件中添加

    1
    2
    3
    RewriteEngine on
    RewriteCond %{SERVER_PORT} !^443$
    RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R]

其他常规发行版指南

  1. 在Apache安装目录中新建cert目录,并将解压的Apache证书、证书链文件和密钥文件拷贝到cert目录中。如果需要安装多个证书,需在Apache目录中新建对应数量的cert目录,用于存放不同的证书 。

  2. 修改httpd.conf - Apache/conf/httpd.conf配置文件。

    1
    2
    #LoadModule ssl_module modules/mod_ssl.so  #删除行首的配置语句注释符号“#”加载mod_ssl.so模块启用SSL服务,Apache默认是不启用该模块的。
    #Include conf/extra/httpd-ssl.conf #删除行首的配置语句注释符号“#”。

    说明 :如果您在httpd.conf文件中没有找到以上配置语句,请确认您的Apache服务器中是否已经安装mod_ssl.so模块。可执行yum install -y mod_ssl命令安装mod_ssl模块。

  3. 修改httpd-ssl.conf - Apache/conf/extra/httpd-ssl.conf配置文件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <VirtualHost *:443>     
    ServerName #修改为申请证书时绑定的域名www.YourDomainName1.com。
    DocumentRoot /data/www/hbappserver/public
    SSLEngine on
    SSLProtocol all -SSLv2 -SSLv3 # 添加SSL协议支持协议,去掉不安全的协议。
    SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM # 修改加密套件。
    SSLHonorCipherOrder on
    SSLCertificateFile cert/domain name1_public.crt # 将domain name1_public.crt替换成您证书文件名。
    SSLCertificateKeyFile cert/domain name1.key # 将domain name1.key替换成您证书的密钥文件名。
    SSLCertificateChainFile cert/domain name1_chain.crt # 将domain name1_chain.crt替换成您证书的密钥文件名;证书链开头如果有#字符,请删除。
    </VirtualHost>

    #如果证书包含多个域名,复制以上参数,并将ServerName替换成第二个域名。
    <VirtualHost *:443>
    ServerName #修改为申请证书时绑定的第二个域名www.YourDomainName2.com。
    DocumentRoot /data/www/hbappserver/public
    SSLEngine on
    SSLProtocol all -SSLv2 -SSLv3 # 添加SSL协议支持协议,去掉不安全的协议。
    SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM # 修改加密套件。
    SSLHonorCipherOrder on
    SSLCertificateFile cert/domain name2_public.crt # 将domain name2替换成您申请证书时的第二个域名。
    SSLCertificateKeyFile cert/domain name2.key # 将domain name2替换成您申请证书时的第二个域名。
    SSLCertificateChainFile cert/domain name2_chain.crt # 将domain name2替换成您申请证书时的第二个域名;证书链开头如果有#字符,请删除。
    </VirtualHost>

    说明 根据操作系统的不同,http-ssl.conf文件也可能存放在conf.d/ssl.conf目录中。需注意您的浏览器版本是否支持SNI功能。如果不支持,多域名证书配置将无法生效。

  4. 重启Apache服务器使SSL配置生效。

    1
    2
    apachectl -k stop
    apachectl -k start
  5. 可选:修改httpd.conf文件,设置HTTP请求自动跳转HTTPS。

    在httpd.conf文件中的<VirtualHost *:80> </VirtualHost>中间,添加以下重定向代码。

    1
    2
    3
    RewriteEngine on
    RewriteCond %{SERVER_PORT} !^443$
    RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R]

火狐有个SSL配置生成器

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
# 这里演示的时仅支持TSLv1.3版本。
# generated 2020-12-10, Mozilla Guideline v5.6, Apache 2.4.38, OpenSSL 1.1.1d, modern configuration
# https://ssl-config.mozilla.org/#server=apache&version=2.4.38&config=modern&openssl=1.1.1d&guideline=5.6

# this configuration requires mod_ssl, mod_socache_shmcb, mod_rewrite, and mod_headers
<VirtualHost *:80>
RewriteEngine On
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>

<VirtualHost *:443>
ServerAdmin 【】
DocumentRoot 【】
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>

SSLEngine on
SSLCertificateFile 【】
SSLCertificateKeyFile 【】
SSLCertificateChainFile 【】

# enable HTTP/2, if available
Protocols h2 http/1.1

# HTTP Strict Transport Security (mod_headers is required) (63072000 seconds)
Header always set Strict-Transport-Security "max-age=63072000"
</VirtualHost>

# modern configuration
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 -TLSv1.2
SSLHonorCipherOrder off
SSLSessionTickets off

SSLUseStapling On
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"

代理

反向代理

首先加载proxyproxy_http模块。

1
sudo a2enmod proxy proxy_http

配置sites-available中的站点配置

1
2
3
4
5
6
7
<VirtualHost *:80>
ServerName example.com
ProxyRequests Off
# 末尾记得加斜杠
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
</VirtualHost>

其他配置

最后记得测试配置文件:apachectl configtest

/etc/apache2/apache2.conf

ServerName 【你的域名】:服务器域名

在不需要的目录上增加规则:Require all denied

/etc/apache2/sites-available/000-default.conf

ServerAdmin 【you@example.com邮箱】:错误页面将会显示这个邮箱

ServerSignature Off:关闭服务器签名

ServerTokens Prod:隐藏 Apache 和 PHP 版本等属性

Docker

配置systemctl服务控制docker容器运行

不是Docker容器内运行systemctl !是使用systemctl控制docker容器的运行

生成容器:sudo docker create --name rsshub -p 1200:1200 diygod/rsshub

服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Unit]
Description=$SRV_NAME
After=network.target

[Service]
ExecStart=start.sh
ExecStop=stop.sh
Type=forking
PrivateTmp=True
# 下面的注释是指定用户运行
# User=xxx

[Install]
WantedBy=multi-user.target

start.shstop.sh内容分别是启动和停止:

启动:docker start -a rsshub&

停止:docker stop rsshub

将服务移动到:/lib/systemd/system/

FFmpeg推流

还可使用kplayer推流(对服务器配置要求高些),具体可以使用https://gitee.com/rmshadows/rm_scripts里面的脚本协助搭建成服务

参考:https://www.bilibili.com/read/cv9687198/

简单推流

ffmpeg -re -i "1.mp4" -vcodec copy -acodec copy -f flv "你的rtmp地址/你的直播码"

控制输出(低带宽)

-r: 帧率

-b: 比特率

ffmpeg -re -stream_loop -1 -i "$MP4_FILE" -r 10 -b 10k -f flv -flvflags no_duration_filesize "$RTMP"&

播放列表

ffmpeg -re -f concat -safe 0 -i playlist.txt -vcodec copy -acodec copy -f flv "rtmp://rtmp地址/你的直播码"

播放列表格式:

1
2
3
file 'input1.mp4'
file 'input2.mp4'
file 'input3.mp4'

单文件循环推流

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
# RTMP地址
RTMP_ADDR="rtmp://"
MP4_FILE="1.mp4"
# 循环 -stream_loop -1
ffmpeg -re -stream_loop -1 -i "$MP4_FILE" -vcodec copy -acodec copy -f flv -flvflags no_duration_filesize "$RTMP_ADDR"

#while true
#do
# ffmpeg -re -i "1.mp4" -stream_loop -1 -vcodec copy -acodec copy -f flv "$RTMP_ADDR"
#done

尝试无缝推流

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
71
72
73
74
75
76
77
78
79
80
管道可以作为一个媒介,管道一端用于接收需要推送的媒体流,另一端则输出给ffmpeg推流到rtmp服务器,那只要管道输出端一直有数据给到ffmpeg推流,那ffmpeg就能一直运行。
管道又分为匿名管道和命名管道,我一开始尝试使用匿名管道发现无法解决问题,匿名管道具有一定的局限性:首先,这个管道只能是具有血缘关系的进程之间通信;第二,它只能实现一个进程写另一个进程读,而如果需要两者同时进行时,就得重新打开一个管道。于是我尝试使用命名管道,关于命名管道:
1、与管道的区别:提供了一个路径名与之关联,以FIFO文件的形式存储于文件系统中,能够实现任何两个进程之间通信。而匿名管道对于文件系统是不可见的,它仅限于在父子进程之间的通信。
2、FIFO是一个设备文件,在文件系统中以文件名的形式存在,因此即使进程与创建FIFO的进程不存在血缘关系也依然可以通信,前提是可以访问该路径。
3、FIFO(first input first output)总是遵循先进先出的原则,即第一个进来的数据会第一个被读走。


1、所有指向管道写端的文件描述符都关闭了(管道写端的引用计数等于0),而仍然有进程从管道的读端读数据时,那么管道中剩余的数据都被读取后,再次read会返回0,就像读到文件末尾一样。

2、指向管道写端的文件描述符没关闭(管道写端的引用计数大于0),而持有管道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据时,管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。

3、所有指向管道读端的文件描述符都关闭了(管道读端的引用计数等于0),这时有进程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。

4、指向管道读端的文件描述符没关闭(管道的引用计数大于0),而持有管道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时再次write会阻塞,直到管道中有空位置了才写入数据并返回。

当管道的写和读都已经打开后,管道读端的引用计数等于0或者写端的引用计数等于0,管道就会关闭,需要重新操作。简单来说,当上面整个操作流程开始后,中断其中一个进程,最后都会导致管道关闭,那么想要维持管道的开启,需要管道读端的引用计数和写端的引用计数都大于0

于是我想了个办法,利用管道的阻塞特点,通过新建两个新的管道文件keep1、keep2,一个指向push的写端,另一个指向push的读端,使push读端和写端的引用计数都不为0,具体如下:


mkfifo keep1

mkfifo keep2

cat keep1 > push

cat keep2 < push


经过测试:

1、推流进程关闭时,输入进程进入阻塞状态,重新开启推流进程,输入进程恢复运行,输入没有重置

2、输入进程关闭时,推流进程进入阻塞状态,重新开启输入进程,推流进程恢复运行,无需重新打开

六、总结

基于Linux系统下通过ffmpeg推流到本站,只需要几个简单的步骤:

1、新建3个命名管道,名字随意

mkfifo keep1

mkfifo keep2

mkfifo push


2、创建输入脚本push.sh,填入

#!/bin/bash

while true

do

ffmpeg -re -f concat -safe 0 -i playlist.txt -vcodec copy -acodec aac -f flv pipe:1.flv | cat - >> push

done


3、创建推流脚本send.sh,填入

#!/bin/bash

ffmpeg -re -i push -c:v copy -c:a aac -f flv "rtmp://rtmp地址/你的直播码"


4、打开四个终端窗口,分别输入:

sh push.sh

sh send.sh

cat keep1 > push

cat keep2 < push


上面几个命令的执行顺序应该不影响最终结果,不想开这么多终端窗口,那就后台运行吧,不过push和send在后台运行的话应该就看不到ffmpeg的打印信息了。

推流地址:

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
#### Twitch TV: 
https://help.twitch.tv/s/twitch-ingest-recommendation?language=zh_CN
参考:https://www.bilibili.com/read/cv22157300?from=search
Recommended Ingest Endpoints For You
These ingests endpoints are selected for you based on the optimal network paths detected from Twitch to your device
ingest
#1US West: Los Angeles, CA
rtmp://lax.contribute.live-video.net/app/{stream_key}
ingest
#2US West: San Jose, California (6)
rtmp://sjc06.contribute.live-video.net/app/{stream_key}
ingest
#3US West: San Francisco, CA
rtmp://sfo.contribute.live-video.net/app/{stream_key}
ingest
#4US West: Phoenix, AZ
rtmp://phx.contribute.live-video.net/app/{stream_key}
ingest
#5US West: Salt Lake City, UT
rtmp://slc.contribute.live-video.net/app/{stream_key}
ingest
#6US West: Portland, OR
rtmp://pdx.contribute.live-video.net/app/{stream_key}
ingest
#7US Central: Denver, CO (52)
rtmp://den52.contribute.live-video.net/app/{stream_key}
ingest
#8US West: Seattle, WA
rtmp://sea.contribute.live-video.net/app/{stream_key}
ingest
#9US West: Seattle, WA (2)
rtmp://sea02.contribute.live-video.net/app/{stream_key}
ingest
#10US Central: Dallas, TX
rtmp://dfw.contribute.live-video.net/app/{stream_key}

#### 花椒直播
https://activity.huajiao.com/web/share/banner/room/obsLive/index.html

rtmp://ps2.live.huajiao.com/live_huajiao_open/2039960881684**********

#### 映客直播
https://www.inke.cn/livemanager/index.html#/stream

rtmp://istream.inke.cn/live/16840716964*****?sign=969d85aa******c9MjAwLWlzdHJlYW0uaW5rZS******3N*****c2NDI%3D&ver=2&uid=752******&ikBeauty=2&ikKnDebug=0&ikEnableDRC=0&ikExposure=0&ikFilter=1&dd_type=0&ikDisableFaceSei=1&ikKnIncr=0&ikLiveType=normal&ikFaceMorph=0

#### 哔哩哔哩
https://link.bilibili.com/p/center/index#/my-room/start-live

rtmp://live-push.bilivideo.com/live-bvc/?streamname=live_47*******_45******&key=25a*******52d****e*******bc*****&schedule=rtmp&pflag=1

srt://live-push.bilivideo.com:1937?streamid=#!::h=live-push.bilivideo.com,r=live-bvc/?streamname=live_47*******_45*****,key=25a576c7**********2de**********7,schedule=srtts,pflag=1?streamname=live_47*******_45*****&key=25*****************de**********7&schedule=rtmp&pflag=1

FRP内网穿透

首先,下载FRP | 文档

0.54.0版

1
2
3
4
wget https://github.com/fatedier/frp/releases/download/v0.54.0/frp_0.54.0_linux_amd64.tar.gz
tar -xzvf ./frp_0.54.0_linux_amd64.tar.gz
rm frp_0.54.0_linux_amd64.tar.gz
mv frp_0.54.0_linux_amd64 frp
安装服务

frps.service

1
2
3
4
5
6
7
8
9
10
11
12
13
[Unit]
# 服务名称,可自定义
Description = frp server
After = network.target syslog.target
Wants = network.target

[Service]
Type = simple
# 启动frps的命令,需修改为您的frps的安装路径
ExecStart = /path/frps -c /path/frps.toml

[Install]
WantedBy = multi-user.target

sudo cp ./frps.service /lib/systemd/system/

服务端

frps.toml

1
2
3
4
5
6
7
8
9
10
11
12
13
bindPort = 7000
auth.method = "token"
auth.token = "aaa"
webServer.port = 7500
# dashboard 用户名密码,可选,默认为空
webServer.user = "a1"
webServer.password = "aaa1"
Log.to = "/home/frp/frps.log"
Log.maxDays=30
# 是否返回详细报错
detailedErrorsToClient = false
# 允许的端口
Server.allowPorts = "3000-5000"
XTCP-P2P

首先需要服务器

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
### 配置需要暴露到外网的机器上的 frpc.toml 文件

serverAddr = "x.x.x.x"
serverPort = 7000
# 如果默认的 STUN 服务器不可用,可以配置一个新的 STUN 服务器
# natHoleStunServer = "xxx"

[[proxies]]
name = "p2p_ssh"
type = "xtcp"
# 只有共享密钥 (secretKey) 与服务器端一致的用户才能访问该服务
secretKey = "abcdefg"
localIP = "127.0.0.1"
localPort = 22

### 在想要访问内网服务的机器上部署 frpc

serverAddr = "x.x.x.x"
serverPort = 7000
# 如果默认的 STUN 服务器不可用,可以配置一个新的 STUN 服务器
# natHoleStunServer = "xxx"

[[visitors]]
name = "p2p_ssh_visitor"
type = "xtcp"
# 要访问的 P2P 代理的名称
serverName = "p2p_ssh"
secretKey = "abcdefg"
# 绑定本地端口以访问 SSH 服务
bindAddr = "127.0.0.1"
bindPort = 6000
# 如果需要自动保持隧道打开,将其设置为 true
keepTunnelOpen = false

### 通过 SSH 访问内网机器
ssh -oPort=6000 test@127.0.0.1

0.37.0版本

配置FRP服务端:

frps.ini

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[common]
# 端口
bind_port = 7000
# 访问令牌
token = xxxx
# 这个是Web监控页面端口
dashboard_port = 100
# dashboard 用户名密码,可选,默认为空
dashboard_user = user
dashboard_pwd = passwd
log_file = /Logs/frp/frps.log
log_max_days=30
# 是否返回详细报错到客户端
detailed_errors_to_client = false
# 允许的端口
allow_ports = 10086-10090

搭建服务:

1
2
3
4
5
6
7
8
9
10
11
[Unit]
Description=Frp Server Service
After=network.target

[Service]
Type=simple
User=nobody
Restart=on-failure
RestartSec=5s
ExecStart=/usr/bin/frps -c /etc/frp/frps.ini
LimitNOFILE=1048576

对应的客户端:

frpc.ini

1
2
3
4
5
6
7
8
9
10
11
[common]
server_addr = vip.frp.wlphp.com
server_port = 7000

[Name]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
token = xxxx
# frp 会为本地服务的 22 端口,在 frps 所在的服务端监听 6000 端口,将 6000 端口接收到的连接和本地服务22 端口关联,透传流量,从而实现让用户在外部访问到内部服务。

Hackchat

首先从Github拉取仓库git clone https://github.com/hack-chat/main.git

进入仓库执行npm install

启动npm start 停止npm stop

内置命令

  1. 登录管理员:随便进入某个房间,在弹出的昵称对话框中输入【管理员用户名】#【管理员密码】

  2. 登录管理员后,可以使用命令:

    1. 直接键入:/help

    2. 打开浏览器开发者工具,控制台输入:

      send({ cmd: 'listusers' });

      send({ cmd: 'addmod', trip: 'thetrip' });

      send({ cmd: 'ban', nick: 'targetNick' });

自定义配置

修改监听端口号

nano ./pm2.config.js,将args: './client -p 3000 -o',中的3000修改为你要的端口号。

修改首页信息、Websocket地址和nginx反向代理配置

nano client/client.js,找到function join(channel)里面的var wsPath = '6060';设置为你要代理的路径即可。

我的首页配置:

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
71
72
73
74
75
var frontpage = [
" _ _ _ _ ",
" | |_ ___ ___| |_ ___| |_ ___| |_ ",
" | |_ || _| '_| | _| |_ || _|",
" |_|_|__/|___|_,_|.|___|_|_|__/|_| ",
"",
"",
"欢迎使用hack.chat,这是一个迷你的、无干扰的加密聊天应用程序。",
"频道是通过url创建、加入和共享的,通过更改问号后的文本来创建自己的频道(请使用英文字母)。",
"如果您希望频道名称(房间名)为:‘ hello ’,请在浏览器地址栏输入: https://civiccccc.ltd/hc/?hello",
"这里没有公开频道列表,因此你可以使用秘密的频道名称(也就是别人都猜不到的房间名)进行私人讨论。在这里,聊天记录不会被记录,聊天信息传输也是加密的(除非你不是用的https访问本站,或者你的电脑遭到攻击)。",
"下面是预设的房间:休息室、元数据、数学、物理、化学、科技、编程、游戏、香蕉",
"",
"",
"?lounge ?meta",
"?math ?physics ?chemistry",
"?technology ?programming",
"?games ?banana",
"",
"",
"",
"",
"# 这里为你随机生成了一个聊天室(请点击链接进入房间): ?" + Math.random().toString(36).substr(2, 8),
"",
"",
"",
"",
"语法支持(支持部分Markdown语法):",
"空格缩进(两个或四个空格)、Tab键是保留字符,因此可以逐字粘贴源代码(回车请用Shift+Enter)。比如:",
"``` # 这是代码```",
"``` #!/bin/bash```",
"``` echo hello```",
"支持LaTeX语法(数学公式),单行显示请用一个美元符号包围数学公式,多行显示(展示公式)请用两个美元符号包围。",
"单行:```$\\zeta(2) = \\pi^2/6$``` $\\zeta(2) = \\pi^2/6$",
"多行:```$$\\int_0^1 \\int_0^1 \\frac{1}{1-xy} dx dy = \\frac{\\pi^2}{6}$$``` $$\\int_0^1 \\int_0^1 \\frac{1}{1-xy} dx dy = \\frac{\\pi^2}{6}$$",
"对于语法突出显示,将代码包装为:```<language> <the code>```其中<language>是任何已知的编程语言。",
"",
"当前的Github代码仓库: https://github.com/hack-chat",
"旧版GitHub代码仓库: https://github.com/AndrewBelt/hack.chat",
"",

"机器人,Android客户端,桌面客户端,浏览器扩展,Docker映像,编程库,服务器模块等:",
"https://github.com/hack-chat/3rd-party-software-list",
"根据WTFPL和MIT开源许可证发布的服务器和Web客户端。",
"hack.chat服务器不会保留任何聊天记录。",
"",
"",
"Welcome to hack.chat, a minimal, distraction-free chat application.",
"Channels are created, joined and shared with the url, create your own channel by changing the text after the question mark.",
"If you wanted your channel name to be 'your-channel': https://hack.chat/?your-channel",
"There are no channel lists, so a secret channel name can be used for private discussions.",
"",
"",
"Here are some pre-made channels you can join:",
"?lounge ?meta",
"?math ?physics ?chemistry",
"?technology ?programming",
"?games ?banana",
"And here's a random one generated just for you: ?" + Math.random().toString(36).substr(2, 8),
"",
"",
"Formatting:",
"Whitespace is preserved, so source code can be pasted verbatim.",
"Surround LaTeX with a dollar sign for inline style $\\zeta(2) = \\pi^2/6$, and two dollars for display. $$\\int_0^1 \\int_0^1 \\frac{1}{1-xy} dx dy = \\frac{\\pi^2}{6}$$",
"For syntax highlight, wrap the code like: ```<language> <the code>``` where <language> is any known programming language.",
"",
"Current Github: https://github.com/hack-chat",
"Legacy GitHub: https://github.com/AndrewBelt/hack.chat",
"",
"Bots, Android clients, desktop clients, browser extensions, docker images, programming libraries, server modules and more:",
"https://github.com/hack-chat/3rd-party-software-list",
"",
"Server and web client released under the WTFPL and MIT open source license.",
"No message history is retained on the hack.chat server."
].join("\n");

Nginx反向代理配置

1
2
3
4
5
6
7
8
9
10
11
# Hack chat
location /hc/ {
#rewrite /$1 ^/hackchat(.*);
proxy_pass http://127.0.0.1:3000/;
}
location /hc-wss {
proxy_pass http://127.0.0.1:6060;
# proxy_http_version 1.1;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "Upgrade";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
git clone https://github.com/hack-chat/main.git
mv main hackchat-main
cd hackchat-main
npm install
echo "#!/bin/bash
cd [Path to hackchat] && npm start" > hc_start.sh
echo "#!/bin/bash
cd [Path to hackchat] && npm stop" > hc_stop.sh
sudo echo "[Unit]
Description=Hackchat
After=network.target

[Service]
ExecStart=Path to /hackchat_srv/hc_start.sh
ExecStop=Path to /hakchat_srv/hc_stop.sh
Type=forking
PrivateTmp=True

[Install]
WantedBy=multi-user.target
" > /lib/systemd/system/hackchat.service
sudo systemctl daemon-reload

ISSO

官网 | 官网-OLD | 中文文档 | 参考自烧饼博客

安装

安装先决条件:apt-get install python-dev build-essential python3-pip -y

装ISSO:pip3 install --upgrade pip && pip3 install isso

安装SQL Lite3:apt-get install sqlite3

新建ISSO配置

新建配置文件sudo nano /etc/isso.conf

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
[general]
dbpath = /isso/comments.db
name = default
host = https://
https://
#notify = smtp
log-file = /isso/isso.log

[server]
listen = http://localhost:20/

#[moderation]
#enabled = true
#purge-after = 30d

#[smtp]
#username = .com
#password = m
#host = 127.0.0.1
#port = 587
#security = starttls
#to = @.com
#from = "Isso Comment"<username@example.com>
#timeout = 10

[markup]
options = strikethrough, superscript, autolink

[guard]
enabled = true
ratelimit = 5
direct-reply = 30
reply-to-self = true
require-author = true
require-email = true

[hash]
salt = Eech7co8Ohloopo9Ol6baimi
algorithm = pbkdf2

[general] 是基本配置,必须填写

dbpath 就是数据库文件,刚才我们已经建立了 /var/lib/isso/ 目录,所以他会自动生成 *必填

name 是这一个配置文件的名字,如果本地只搭建一个 Isso 的话可以忽略,搭建多个 Isso 的话需要设置 *可选

host 是你引用 Isso 的 JS 的网站地址,需要写全,如果有多个的话就多加几行,只有一个域名的话留下一个即可 *必填

notify 评论审核通知方式,如果不开启审核可以不设置,设置了 SMTP 就需要在下面的 [smtp] 设置邮件发送方式 *可选

log-file 记录日志,后续我们会提到,一般不需要开启

[server] 本地服务端设置

listen 需要监听的端口,可以自定义,这里我们用 8090 为例

1
[moderation]` 是否开启评论审核,不需要的话可以写 `enabled = false

purge-after 指定多少时间后删除还在审核队列里的评论

[markup]Misaka Markdown 插件

1
options` 可选 `strikethrough`, `superscript`, `autolink` 比如不需要自动加入超链接可以去掉 `autolink

allowed-elements 评论开启 HTML 标签,默认允许的标签有 a, blockquote, br, code, del, em, h1, h2, h3, h4, h5, h6, hr, ins, li, ol, p, pre, strong, table, tbody, td, th, theadul 可以根据自己情况修改

1
allowed-attributes` 评论开启 HTML 标签的属性,默认只允许 `align` 和 `href

[smtp] 审核评论发送邮件通知的设置,具体可以咨询你使用的邮件服务,按服务商提供的配置填写即可,不再详细描述

1
[guard]` 开启评论防火墙,如不需要可以填写 `enabled = false

ratelimit 每个访客一分钟最多可以评论的次数

direct-reply 评论回复次数

reply-to-self 是否可以回复自己的评论,需要配合 JS 引用,下面会说

require-author 是否要求写名字,需要配合 JS 引用,下面会说

require-email 是否要求写 Email 地址,需要配合 JS 引用,下面会说

[hash] 加密评论的身份方式,如 Email 地址,没有特殊需求可以忽略

Nginx代理

1
2
3
4
5
6
7
8
# isso 评论系统
location /sub {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Script-Name /sub;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:port;
}

引入代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script data-isso="http://example.com/isso/"
data-isso-css="true"
data-isso-lang="en"
data-isso-reply-to-self="false"
data-isso-require-author="false"
data-isso-require-email="false"
data-isso-max-comments-top="10"
data-isso-max-comments-nested="5"
data-isso-reveal-on-click="5"
data-isso-avatar="true"
data-isso-avatar-bg="#f0f0f0"
data-isso-avatar-fg="#9abf88 #5698c4 #e279a3 #9163b6 ..."
data-isso-vote="true"
data-vote-levels=""
src="http://example.com/isso/js/embed.min.js"></script>

<section id="isso-thread"></section>

data-isso Isso 安装的 URI

1
data-isso-css` 使用默认的 CSS 如果需要自己改 CSS 则设置成 `false

data-isso-lang 默认语言,参考 ISO 639-1 编码,可选语言列表在这儿

data-isso-reply-to-selfdata-isso-require-authordata-isso-require-email 需按照 Isso 配置文件来,请保持一致

data-isso-max-comments-top 一页显示的评论数

data-isso-max-comments-nested 最多嵌套评论数

data-isso-reveal-on-click 超出评论数后点击显示的评论数

data-isso-avatar 显示头像

data-isso-avatar-bg 头像背景

data-isso-avatar-fg 头像颜色

data-isso-vote 开启评论的支持和反对

data-vote-levels 评论支持和反对的等级算法,具体请参考官方的文档

1
2
3
4
sudo apt update && sudo apt upgrade
sudo apt-get install python-dev build-essential python3-pip -y
pip3 install --upgrade pip && pip3 install isso
sudo apt-get install sqlite3

JAMS——Jami Server

Jami是一款跨平台聊天软件

官网:https://jami.net/ JAMS:https://jami.biz/ JAMS下载:https://dl.jami.net/jams/jams.tar

下载:wget https://dl.jami.net/jams/jams.tar

解压:tar -xvf jams.tar

生成SSL证书(非必选):openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout server.key -out server.pem

运行:java -jar jams-launcher.jar PORT_NUMBER (eg. 8443 or 443) server.pem server.key

设置服务:sudo nano /lib/systemd/system/jams.service

1
2
3
4
5
6
7
8
9
10
[Service] 
Type=simple
WorkingDirectory=[DIRECTORY WHERE JAMS WAS UNZIPPED]
ExecStart=/usr/bin/java -jar [DIRECTORY WHERE JAMS WAS UNZIPPED]/jams-launcher.jar PORT SSL_CERTIFICATE SSL_CERTIFICATE_KEY

[Install]
WantedBy=multi-user.target
# The parameters PORT, SSL_CERTIFICATE and SSL_CERTIFICATE_KEY are optional (however,
# PORT can be used alone whereas the SSL_CERTIFICATE comes in pair with
# SSL_CERTIFICATE_KEY)

配置Nginx代理:

1
2
3
4
5
6
7
8
9
10
11
12
13
server { 
listen 443 ssl;
listen [::]:443 ssl;
ssl on;
ssl_certificate /etc/certificates/mycertificate.pem
ssl_certificate_key /etc/certificates/mycertificatekey.pem
client_max_body_size 100M; server_name jams.mycompany.com;
location / {
proxy_pass http://10.10.0.1:8080/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
}
}

Jitsi-Meet

Jitsi-Meet是开源在线会议

官网 手册 在线会议

配置需求

  • 网络环境:基本的速度和可靠性是必不可少的。 使用任何下载工具(或 ftp)检查提供商声称的速度,以及 使用 iperf3 等工具验证延迟。 精确的计算非常复杂,并且依赖于许多优化和技巧,但您至少应该记住这些关于分辨率的数字: 180 = 200 比特/秒360 = 500 比特/秒720(高清)= 2500 kbits/s4k = 10 兆比特/秒。 所以不要指望有 20 个用户在 100Mbits/s 上传和下载的服务器上使用 4K。 对于小型组织服务器,1 Gbits/s 通常就足够了,但对于大型服务器 10 Gbits/s 是可取的。 大型部署使用几个(或许多…)网桥,每个网桥都有一个 10 Gbits/s 的链路。
  • RAM: 通常建议获得 8 GB。 对于小型会议,您可以使用 4 GB,对于测试服务器或非常小的会议,您可以尝试使用 2 GB。 对于大型会议,建议采用可扩展的方式来获取大量内存。

  • CPU: 非常低的处理器性能会严重损害实时系统,尤其是在使用共享服务器时(您的 CPU 性能可能会被主机的其他客户窃取,如果您获得的是 VPS,请检查“专用 CPU”,而不是物理服务器)。 但是,需要考虑的是 Jitsi Meet 组件 Prosody 只能使用一 (1) 个核心。 所以获得很多核心,比方说超过 32 个,并不总是有用。 对于基本服务器,4 个专用内核就足够了。

  • 磁盘: 除非您正在进行大量日志记录或有非常特殊的需求,否则您可以使用 20 GB 的标准硬盘。 SSD 与其说是必需品,不如说是锦上添花。

安装

推荐使用Docker安装,手动构建可能出现依赖冲突问题

Docker

注意:DO NOT clone the git repository. 不要克隆仓库

直接去Release下载发布,解压。

  1. 生成配置文件cp env.example .env,并自行修改配置文件(TZHTTP_PORTHTTPS_PORTDOCKER_HOST_ADDRESSPUBLIC_URL)。

  2. 生成随机密码./gen-passwords.sh

  3. 创建文件夹mkdir -p ~/.jitsi-meet-cfg/{web,transcripts,prosody/config,prosody/prosody-plugins-custom,jicofo,jvb,jigasi,jibri}

  4. 运行、启动:docker-compose up -d

  5. 开放防火墙端口:

    1
    2
    3
    4
    80/tcp for Web UI HTTP (really just to redirect, after uncommenting ENABLE_HTTP_REDIRECT=1 in .env)
    443/tcp for Web UI HTTPS
    4443/tcp for RTP media over TCP
    10000/udp for RTP media over UDP
  6. 配置nginx:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    location /xmpp-websocket {
    proxy_pass https://localhost:8443;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    }
    location /colibri-ws {
    proxy_pass https://localhost:8443;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    }

    或者Apache2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <IfModule mod_proxy.c>
    <IfModule mod_proxy_wstunnel.c>
    ProxyTimeout 900
    <Location "/xmpp-websocket">
    ProxyPass "wss://localhost:8443/xmpp-websocket"
    </Location>
    <Location "/colibri-ws/">
    ProxyPass "wss://localhost:8443/colibri-ws/"
    </Location>
    </IfModule>
    </IfModule>
Debian

安装前建议只保留一个HTTP服务器,nginx、apache2只留一个。

  1. 更新apt

    1
    2
    3
    4
    5
    # Retrieve the latest package versions across all repositories
    sudo apt update

    # Ensure support for apt repositories served via HTTPS
    sudo apt install apt-transport-https
  2. 设置主机名sudo hostnamectl set-hostname meet.example.org

  3. 设置/etc/hosts

    1
    2
    127.0.0.1 localhost
    x.x.x.x meet.example.org
  4. 添加Jitsi-meet仓库

    1
    2
    3
    4
    5
    6
    7
    8
    # 安装lua(可选)
    echo deb http://packages.prosody.im/debian $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list
    wget https://prosody.im/files/prosody-debian-packages.key -O- | sudo apt-key add -
    apt install lua5.2

    # 添加Jitsi仓库
    curl https://download.jitsi.org/jitsi-key.gpg.key | sudo sh -c 'gpg --dearmor > /usr/share/keyrings/jitsi-keyring.gpg'
    echo 'deb [signed-by=/usr/share/keyrings/jitsi-keyring.gpg] https://download.jitsi.org stable/' | sudo tee /etc/apt/sources.list.d/jitsi-stable.list > /dev/null
  5. 打开防火墙

    • 80 TCP => For SSL certificate verification / renewal with Let’s Encrypt. Required
    • 443 TCP => For general access to Jitsi Meet. Required
    • 10000 UDP => For General Network Audio/Video Meetings. Required
    • 22 TCP => For Accessing your Server using SSH (change the port accordingly if it’s not 22). Required
    • 3478 UDP => For querying the stun server (coturn, optional, needs config.js change to enable it).
    • 5349 TCP => For fallback network video/audio communications over TCP (when UDP is blocked for example), served by coturn. Required
    1
    2
    3
    4
    5
    6
    7
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw allow 10000/udp
    sudo ufw allow 22/tcp
    sudo ufw allow 3478/udp
    sudo ufw allow 5349/tcp
    sudo ufw enable
  6. 安装Jitsi-Meet,会询问问题,需要回答问题才能继续安装:sudo apt update && sudo apt install jitsi-meet

  7. (可选)Systemd/Limits:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Default deployments on systems using systemd will have low default values for maximum processes and open files. If the used bridge will expect higher number of participants the default values need to be adjusted (the default values are good for less than 100 participants).

    To update the values edit /etc/systemd/system.conf and make sure you have the following values if values are smaller, if not do not update.

    DefaultLimitNOFILE=65000
    DefaultLimitNPROC=65000
    DefaultTasksMax=65000

    To check values just run:

    systemctl show --property DefaultLimitNPROC
    systemctl show --property DefaultLimitNOFILE
    systemctl show --property DefaultTasksMax
  8. 同理,nginx配置文件需要检查一下(按道理安装的时候就自动配置好了)

  9. (卸载)如果你不想要Jitsi-meet了,卸载请用:sudo apt purge jigasi jitsi-meet jitsi-meet-web-config jitsi-meet-prosody jitsi-meet-turnserver jitsi-meet-web jicofo jitsi-videobridge2

完整的jitsi-meet nginx配置文件看起来可能是:

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# generated 2021-03-20, Mozilla Guideline v5.6, nginx 1.14.2, OpenSSL 1.1.1d, modern configuration
# https://ssl-config.mozilla.org/#server=nginx&version=1.14.2&config=modern&openssl=1.1.1d&guideline=5.6

# rewrite module from firefox ssl config generator
server {
listen 80 default_server;
listen [::]:80 default_server;
return 301 https://$host$request_uri;
}

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
#域名
server_name jitsi.name;
# index index.html index.htm index.php;
#站点目录
# root /home/nginx/;
#错误页
# error_page 301 302 403 404 502 /404.html; #错误
access_log /Logs/nginx/443-access.log;
error_log /Logs/nginx/443-error.log;

location / {
proxy_pass https://127.0.0.1:8443;
}

location /xmpp-websocket {
proxy_pass https://localhost:8443;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

location /colibri-ws {
proxy_pass https://localhost:8443;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

ssl_certificate /etc/ssl/jitsi.pem;
ssl_certificate_key /etc/ssl/jitsi.key;
ssl_session_timeout 180m;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;

# modern configuration
#ssl_protocols TLSv1.3;
#ssl_prefer_server_ciphers off;

# ali_cloud_config
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #表示使用的TLS协议的类型。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; #表示使用的加密套件的类型。
ssl_prefer_server_ciphers on;

# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;

# OCSP stapling
# ssl_stapling on; # 启用OCSP响应验证,OCSP信息响应适用的证书
# ssl_stapling_verify on;
# verify chain of trust of OCSP response using Root CA and Intermediate certs
# ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;
# replace with the IP address of your resolver
# resolver 127.0.0.1;
}

# 其他目录
server {
listen 200 ssl http2;
listen [::]:200 ssl http2;
server_name jitsi.name;#域名
index index.html index.htm index.php;
root /home/nginx/;#站点目录

access_log /Logs/nginx/200-access.log;
error_log /Logs/nginx/200-error.log;

# 用户分享的文件
location / {
autoindex on;
autoindex_exact_size off;
autoindex_localtime off;
}

ssl_certificate /etc/ssl/jitsi.pem;
ssl_certificate_key /etc/ssl/jitsi.key;
ssl_session_timeout 180m;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;

# modern configuration
#ssl_protocols TLSv1.3;
#ssl_prefer_server_ciphers off;

# ali_cloud_config
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #表示使用的TLS协议的类型。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; #表示使用的加密套件的类型。
ssl_prefer_server_ciphers on;
}

Linx-server

文件共享服务器,使用Go语言编写,需要自行编译。

此 文件共享服务器是限时分享,超时文件将被销毁。

功能:

  1. 文件共享
  2. 命令行上传(API)
  3. 多平台客户端(Windows、Linux、Android),客户端链接见文末
  4. 临时文件共享(无需登录)
  5. 限时文件共享(可设置文件共享时长,超时文件销毁)
  6. 支持鉴权,API Key登录
  7. 文件大小限制
  8. 支持文件预览
  9. 代码共享
  10. 支持配置访问密码
  11. 支持生成种子下载

客户端:

安装

首先安装golangaclgit

克隆仓库:git clone https://github.com/ZizzyDizzyMC/linx-server.git

cd linx-server

编译三个文件:

主文件:go build

其他文件:分别进入linx-genkeylinx-cleanup文件夹中执行go build

配置文件linx-server.conf:

1
2
3
4
5
6
7
8
9
10
11
12
13
bind = 127.0.0.1:8000
sitename = File Sharing
siteurl = https://yourdomain/
selifpath = s
maxsize = 4294967296
maxexpiry = 86400
allowhotlink = true
remoteuploads = true
nologs = true
force-random-filename = false
cleanup-every-minutes = 5
realip = true
fastcgi = true

nginx配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
root /file-sharing;
index index.html index.htm index.nginx-debian.html;
server_name yours;
client_max_body_size 4096M;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
fastcgi_pass 127.0.0.1:8000;
include fastcgi_params;
}

ssl_certificate /etc/ssl/xxx.pem;
ssl_certificate_key /etc/ssl/xxx.key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=63072000" always;
}

运行:./linx-server -config linx-server.conf

目录结构

  • files——上传的文件
  • linx-cleanup——清理过期文件
  • linx-genkey——API Key
  • linx-server——主文件
  • linx-server.conf——配置文件
  • meta——过期的文件

自定义主页

修改templates文件夹中的文件后运行go build,然后替换主文件即可。

关于写入权限

注意运行的时候用的www-data用户,所以如果目录www-data用户访问不了,无法写入的,自然上传失败

Matterbridge

桥接Telegram 和 IRC

Telegram机器人要自己申请,然后关闭机器人隐私模式(privacy mode)

截至2022年12月支持mattermost, IRC, gitter, xmpp, slack, discord, telegram, rocketchat, twitch, ssh-chat, zulip, whatsapp, keybase, matrix, microsoft teams, nextcloud, mumble, vk等。

仓库

下载和安装

直接下载可执行文件

如:wget -O matterbridge-linux https://github.com/42wim/matterbridge/releases/download/v1.25.2/matterbridge-1.25.2-linux-64bit

配置文件matterbridge.toml

所有配置参见Wiki

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
[general]
# 如果你有配置媒体服务器的话 https://github.com/42wim/matterbridge/wiki/Mediaserver-setup-%28advanced%29
MediaDownloadPath="/nginx/matterbridge"
MediaServerDownload="https://media/matterbridge"
# 日志文件
LogFile="/Logs/matterbridge/matterbridge.log"
# ShowJoinPart=true

[telegram.mytelegram]
#See https://core.telegram.org/bots#6-botfather
#and https://www.linkedin.com/pulse/telegram-bots-beginners-marco-frau
# 你的机器人Token
Token=""
RemoteNickFormat="({PROTOCOL}) {NICK} "
MessageFormat="HTMLNick"
# QuoteLengthLimit=5000
# Don't bridge bot commands (as the responses will not be bridged)
# IgnoreMessages="^/"

[irc.myirc]
# 如果你是Libera IRC的话
Server="irc.libera.chat:6697"
# 你的昵称
Nick="nickname"
UseTLS=true
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
RejoinDelay=4
ColorNicks=true
# Flood control. Delay in milliseconds between each message send to the IRC server.
MessageDelay=1500
# 长消息分段
MessageSplit=true
# MessageClipped="<Next Msg>"
MessageClipped=" "
# 消息队列(长消息支持)
MessageQueue=1000
# NickServNick="nickserv"
# NickServPassword="secret"
# NickServUsername="username"
# UseSASL=true
# VerboseJoinPart=true
Charset="utf-8"
# IgnoreMessages="^~~ badword"
# NoSendJoinPart=false
# IgnoreNicks="ircspammer1 ircspammer2"
# JoinDelay=1000


[[gateway]]
name="gateway-irc-tg"
enable=true

# IRC Gateway
[[gateway.inout]]
account="irc.myirc"
# 要加入的频道名称
channel="#channel"
# options = { key="password" }

# Telegram Gateway
[[gateway.inout]]
account="telegram.mytelegram"
# Telegram群组ID,一个负数
channel="-189174892374"

运行

可以作为服务运行

start_matterbridge.sh

1
2
3
#!/bin/bash
cd /path/to/Applications/matterbridge/
./matterbridge-1.25.2-linux-64bit&

matterbridge.service

1
2
3
4
5
6
7
8
9
10
11
12
[Unit]
Description=Matterbridge服务
After=network.target

[Service]
ExecStart=/path/to/Applications/matterbridge/start_matterbridge.sh
Type=forking
PrivateTmp=True
User=User

[Install]
WantedBy=multi-user.target

NGINX

主配置/etc/nginx/nginx.conf

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#### nginx配置
# nginx用户
user www-data;
# 工作核心数量
worker_processes auto;
# 指定nginx进程运行文件存放地址
pid /run/nginx.pid;
# 包含启用的模块
include /etc/nginx/modules-enabled/*.conf;#

#制定日志路径,级别。这个设置可以放入全局块,http块,server块,级别以此为:debug|info|notice|warn|error|crit|alert|emerg
error_log /Logs/nginx/nginx_error.log crit;
# Specifies the value for maximum file descriptors that can be opened by this process.# nginx worker进程最大打开文件数
worker_rlimit_nofile 4028;

events
{
# 在linux下,nginx使用epoll的IO多路复用模型
use epoll;
# nginx worker单个进程允许的客户端最大连接数
worker_connections 1024;
# 设置网路连接序列化,防止惊群现象发生,默认为on.惊群现象:一个网路连接到来,多个睡眠的进程被同时叫醒,但只有一个进程能获得链接,这样会影响系统性能。
accept_mutex on;
# 设置一个进程是否同时接受多个网络连接,默认为off。如果web服务器面对的是一个持续的请求流,那么启用multi_accept可能会造成worker进程一次接受的请求大于worker_connections指定可以接受的请求数。这就是overflow,这个overflow会造成性能损失,overflow这部分的请求不会受到处理。
# multi_accept on;
}

http
{
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_for';

# charset gb2312;
charset utf-8;

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

server_names_hash_bucket_size 128;
# server_name_in_redirect off;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
# 允许客户端请求的最大单文件字节数。如果有上传较大文件,请设置它的限制值
client_max_body_size 25m;

types_hash_max_size 2048;
# 禁用服务器版本显示
server_tokens off;
sendfile on;
# 只有sendfile开启模式下有效
tcp_nopush on;
# 长连接超时时间,单位是秒,这个参数很敏感,涉及浏览器的种类、后端服务器的超时设置、操作系统的设置,可以另外起一片文章了。长连接请求大量小文件的时候,可以减少重建连接的开销,但假如有大文件上传,65s内没上传完成会导致失败。如果设置时间过长,用户又多,长时间保持连接会占用大量资源。
keepalive_timeout 60;
# 设置客户端连接保持会话的超时时间,超过这个时间,服务器会关闭该连接。
tcp_nodelay on;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;

#limit_zone crawler $binary_remote_addr 10m;

##
# SSL Settings
##
# ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
# ssl_prefer_server_ciphers on;

##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

##
# Gzip Settings
##
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_types text/plain application/x-javascript text/css application/xml;
gzip_vary on;
# Nginx作为反向代理的时候启用,决定开启或者关闭后端服务器返回的结果是否压缩,匹配的前提是后端服务器必须要返回包含"Via"的 header头。
# gzip_proxied any;

##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

##
# http_proxy 设置
##
#支持客户端的请求方法。post/get;
# proxy_method post;
# client_max_body_size 10m;
client_body_buffer_size 128k;
# nginx跟后端服务器连接超时时间(代理连接超时)
proxy_connect_timeout 75;
proxy_send_timeout 75;
# 连接成功后,与后端服务器两个成功的响应操作之间超时时间(代理接收超时)
proxy_read_timeout 75;
# 设置代理服务器(nginx)从后端realserver读取并保存用户头信息的缓冲区大小,默认与proxy_buffers大小相同,其实可以将这个指令值设的小一点
proxy_buffer_size 4k;
# proxy_buffers缓冲区,nginx针对单个连接缓存来自后端realserver的响应,网页平均在32k以下的话,这样设置
proxy_buffers 4 32k;
# 高负荷下缓冲大小(proxy_buffers*2)
proxy_busy_buffers_size 64k;
# 当缓存被代理的服务器响应到临时文件时,这个选项限制每次写临时文件的大小。proxy_temp_path(可以在编译的时候)指定写到哪那个目录。
# proxy_temp_file_write_size 64k;
# proxy_temp_path /usr/local/nginx/proxy_temp 1 2;
proxy_hide_header X-Powered-By;
proxy_hide_header Server;

##
# 设定负载均衡后台服务器列表
##
## down,表示当前的server暂时不参与负载均衡。
## backup,预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻。
# upstream mysvr {
# #ip_hash;
# server 192.168.10.100:8080 max_fails=2 fail_timeout=30s ;
# server 192.168.10.101:8080 max_fails=2 fail_timeout=30s ;
# }
}

#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}

注意事项

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
Debian的nginx结构
https://wiki.debian.org/Nginx/DirectoryStructure

注意事项
https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/

# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
# pass PHP scripts to FastCGI server
#
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php-fpm (or other unix sockets):
# fastcgi_pass unix:/run/php/php7.3-fpm.sock;
# # With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}

Nginx显示网站目录文件列表

1
2
3
4
5
location 【path】 {
autoindex on;
autoindex_exact_size off;
autoindex_localtime off;
}

加密的目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 主文件添加:limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
location /crypt {
autoindex on;
# 突发请求不超过10个
limit_req zone=one burst=10;
auth_basic "Passwd required"; #提示信息(自定义)
auth_basic_user_file /home/jessie/Logs/nginx_login; #生成的密码文件
}

# 生成密码文件:
apt-get install apache2-utils
htpasswd -c 【配置文件路径】 【用户名】

-c:创建一个加密文件
-n:不更新加密文件,只将加密后的用户名密码显示在屏幕上
-m:默认采用MD5算法对密码进行加密
-d:采用CRYPT算法对密码进行加密
-p:不对密码进行进行加密,即明文密码
-s:采用SHA算法对密码进行加密
-b:在命令行中一并输入用户名和密码而不是根据提示输入密码
-D:删除指定的用户

禁止访问某些后缀的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
location ~* ^/xxx.html {
return 301 /404.html;
}

location ~* \.(ini|php|cfg|sh|py|conf)$ {
return 301 /404.html;
# deny all;
}

# 根目录下的部分文件夹全为404
location ~* ^/(.xxx) {
return 301 /404.html;
}

解决Nginx无法访问js等文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 很久之前的了,不知道还行不行
location ~ \.css {
add_header Content-Type text/css;
}
location ~ \.js {
add_header Content-Type application/x-javascript;
}

# 如果是404问题,请使用rewrite
# 比如,把img开头的链接重写为/s/img/
# $1是括号里的东西的代称
location /img/ {
rewrite ^/img/(.*)$ /s/img/$1;
# rewrite_log on;
}
location /js/ {
rewrite ^/js/(.*)$ /s/js/$1;
# rewrite_log on;
}

限制IP

查看IP访问次数:

sudo awk '{print $1}' /var/log/nginx/access.log |sort |uniq -c|sort -n

新建文件:sudo nano deny.ip.conf

添加IP:deny 165.91.122.67;

在nginx配置文件中引入:include deny.ip.conf;

Nginx反向代理 - Reverse Proxy

https://www.nginx.com/resources/wiki/start/topics/examples/likeapache/#nginx

Apache

Let’s say we want to establish simple proxy between myhost:80 and myapp:8080. The Apache rule is simple:

1
2
3
4
5
6
<VirtualHost myhost:80>
ServerName myhost
DocumentRoot /path/to/myapp/public
ProxyPass / http://myapp:8080/
ProxyPassReverse / http://myapp:8080/
</VirtualHost>

But NGINX does not have ProxyPassReverse… The solution is adding a few missing HTTP headers.

See also

proxy_redirect. This wiki is partly incorrect. If you need to do location header rewriting, then you will need to use proxy_redirect as well.

NGINX

1
2
3
4
5
6
7
8
9
10
11
server {
listen myhost:80;
server_name myhost;
location / {
root /path/to/myapp/public;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://myapp:8080;
}
}
末尾加不加斜杠的区别
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
From:https://www.jianshu.com/p/c751250a5112
# http://localhost/api1/xxx -> http://localhost:8080/api1/xxx
location /api1/ {
proxy_pass http://localhost:8080;
}

# http://localhost/api2/xxx -> http://localhost:8080/xxx
location /api2/ {
proxy_pass http://localhost:8080/;
}

# http://localhost/api3/xxx -> http://localhost:8080/api3/xxx
location /api3 {
proxy_pass http://localhost:8080;
}

# http://localhost/api4/xxx -> http://localhost:8080//xxx,请注意这里的双斜线,好好分析一下。
location /api4 {
proxy_pass http://localhost:8080/;
}

# http://localhost/api5/xxx -> http://localhost:8080/hahaxxx,请注意这里的haha和xxx之间没有斜杠,分析一下原因。
location /api5/ {
proxy_pass http://localhost:8080/haha;
}

# http://localhost/api6/xxx -> http://localhost:8080/haha/xxx
location /api6/ {
proxy_pass http://localhost:8080/haha/;
}

# http://localhost/api7/xxx -> http://localhost:8080/haha/xxx
location /api7 {
proxy_pass http://localhost:8080/haha;
}

# http://localhost/api8/xxx -> http://localhost:8080/haha//xxx,请注意这里的双斜杠。
location /api8 {
proxy_pass http://localhost:8080/haha/;
}


# 对于不带URI方式,nginx将会保留location中路径部分,在访问http://localhost/api1/xxx时,会代理到http://localhost:8080/api1/xxx
location /api1/ {
proxy_pass http://localhost:8080;
}


# 对于带URI方式,nginx将使用诸如alias的替换方式对URL进行替换,并且这种替换只是字面上的替换。当访问http://localhost/api2/xxx时,http://localhost/api2/(注意最后的/)被替换成了http://localhost:8080/,然后再加上剩下的xxx,于是变成了http://localhost:8080/xxx
location /api2/ {
proxy_pass http://localhost:8080/;
}


# 当访问http://localhost/api5/xxx时,http://localhost/api5/被替换成了http://localhost:8080/haha,请注意这里haha后面没有/,然后再加上剩下的xxx,即http://localhost:8080/haha+xxx=http://localhost:8080/hahaxxx
location /api5/ {
proxy_pass http://localhost:8080/haha;
}

参考:http://sawers.com/blog/reverse-proxying-with-nginx/ —— Mark Sawers

Option 1: Subdomain

Subdomain.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
events {
worker_connections 1024;
}

http {
...

server {
server_name app-a.example.com;

listen 443 ssl;
ssl_certificate /etc/nginx/cert/certificate.pem;
ssl_certificate_key /etc/nginx/cert/key.pem;

proxy_pass http://10.0.4.14:8080;
}
}

这里的app-a托管在10.0.4.14上,并在端口8080上提供服务。在本示例中,我们使用静态IP,但是您可以使用子域,例如app-a.private.example.com,也可以使用内部(VPC-facing)负载均衡器。

该路径未设置,并且隐式传递而无需转换。因此,例如,对https://app-a.example.com/report/cust/67?mode=monthly的请求将作为http://10.0.4.14:8080/report/cust/67?mode=monthly传递。

进入app-a的请求看起来就像是从代理启动的。因此最好添加一些标头以表明已被代理:

1
2
3
4
5
6
7
server {
...
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Proto $scheme;
}
Option 2: Port

Port.png

1
2
3
4
5
6
7
8
9
10
11
12
...
http {
...

server {
listen 8443 ssl;
ssl_certificate /etc/nginx/cert/certificate.pem;
ssl_certificate_key /etc/nginx/cert/key.pem;

proxy_pass http://10.0.4.15:8080;
}
}

这里app-b托管在10.0.4.15上,并在端口8080上提供服务。

您必须打开8443才能在Nginx主机防火墙(和/或安全组,网络ACL等)上入站。

Option 3: Symmetric Path

Symmetric.png

1
2
3
4
5
6
7
8
9
10
11
12
13
...
http {
...

server {
listen 443 ssl;
...

location /app-c {
proxy_pass http://10.0.4.16:8080/app-c;
}
}
}

这里app-c托管在10.0.4.16上,并在端口8080上提供。

The location expression is a prefix match without any modifiers. You can get fancy with exact and regex matches. (See here for a great intro).

位置表达式是没有任何修饰符的前缀匹配。您可以完全匹配和正则表达式匹配。(有关介绍,请参见此处)。

如果应用将重定向发送到其主机/端口,则可以使用以下方法解决此问题:

1
2
3
4
location /app-c {
...
proxy_redirect http://$proxy_host/ $scheme://$host:$server_port/;
}

This will take the Location header in the response, and replace the string http://10.0.4.16:8080 with nginx’s scheme, host and port. So let’s say app-c redirects requests to /app-c to /app-c/landing.html. The 301 redirect is to http://10.0.4.16:8080/app-c/landing.html, the above directive will transform it to https://www.example.com:443/app-c/landing.html. The browser then makes a call back to that URL.

Take note, the terminology and variable use is odd. The $proxy_ variables are the origin servers or target server, and do not refer to the nginx proxy. The $proxy_host variable includes the host and port. The $proxy_port variable does exist and it contains only the port. The $host only contains the nginx host, and the $server_port is separate.

这将在响应中使用Location标头,并将字符串http://10.0.4.16:8080替换为nginx的方案,主机和端口。因此,假设app-c将请求重定向到/app-c/app-c/landing.html。301重定向到http://10.0.4.16:8080/app-c/landing.html,上述指令会将其转换为https://www.example.com:443/app-c/landing.html。然后,浏览器将对该URL进行回叫。

请注意,术语和变量用法很奇怪。$ proxy_变量是原始服务器或目标服务器,并且不引用nginx代理。$ proxy_host变量包括主机和端口。$ proxy_port变量确实存在,并且仅包含端口。$ host仅包含nginx主机,而$ server_port是单独的。

Option 4: Asymmetric Path

Asymmetric.png

使用100%相对URL的应用程序可能会让您很幸运,而且不需要进行任何内容转换。但应用程序经常使用绝对URI和/或绝对URL(协议://主机:端口/路径)引用其自身的内容,并使用多种机制,例如,anchor href,图像和链接src,css @import和JavaScript-建立动态路径。对于目标应用程序中的每个使用模式,您将需要一个转换指令。

它可能需要数天的反复试验。您肯定需要浏览器的开发人员工具视图。您将非常熟悉应用程序的内部,在整个应用程序中导航,检查它如何加载外部文件(HTML,JavaScript,CSS和媒体)。单页AJAX / Comet和现代框架(Angular,React和Vue)可能特别具有挑战性,因为可以通过编程方式构建URL。

这也是最脆弱的方法。经过所有最初的代理工作后,开发人员可以在将来的升级中更改内容访问方法,并且您需要修复反向代理规则。

我在此选项中使用的两个主要指令是:

  1. 重写请求URI更改
  2. sub_filter用于响应内容的更改

sub_filter使用固定的字符串替换,并涵盖了我遇到的所有情况。(我还没有使用过它,但是您可以使用非标准的替换模块进行重建以获得正则表达式的功能。)

假设目标应用在http://10.0.4.17:8080/origin-d上投放,而我们在https://www.example.com/app-d上发布。添加一个位置块,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
http {
...

server {
listen 443 ssl;
...

location /app-d {
rewrite /origin-d$1 /app-d(.*);
proxy_pass http://10.0.4.16:8080/origin-d;
proxy_redirect http://$proxy_host/origin-d/ $scheme://$host:$server_port/app-d/;
sub_filter 'href="/origin-d' 'href="/app-d';
}
}
}

在重写中,proxy_redirect和sub_filter,第一个参数是要匹配的字符串,第二个参数是要替换的字符串。

  • 重写将/app-d/product/list?category=blue之类的URL更改为/origin-d/product/list?category=blue
  • 重定向更改了响应中的Location头,以便它与发布的路径一起使用。
  • 最后,sub_filter在响应主体中创建超链接以使用发布的路径。

您需要为应用程序中使用的其他模式添加其他sub_filter语句。

我通常添加的其他一些内容:

1
2
3
4
5
6
location /app-d {
...
sub_filter_types *;
sub_filter_once off;
sub_filter_last_modified on;
}

sub_filter_types将其应用于所有内容类型。默认情况下,它仅适用于text / html,但是通常您需要更改js和css。

sub_filter_once默认情况下处于启用状态,这意味着它匹配一次并停止。那有多有用?一点也不。您要替换每个实例。请记住,每个字符串都会被替换一次,因此您无法使用两个规则替换说 http://10.0.4.16:8080/origin-d/blah/blah的两个规则,一个规则用于http://$proxy_host,另一个规则用于/origin-d。您将需要一个带有完整URL的规则。

在未将sub_filter_last_modified设置为on的情况下,您将破坏所有客户端(以及可能的其他中间代理)缓存。启用此选项后,将在替换期间从原始响应中保留“最后修改的”标头字段,以启用上游响应缓存。

注意事项:

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
# from https://www.cnblogs.com/kevingrace/p/7133806.html
location ^~ /wangshibo/
{
proxy_cache js_cache;
proxy_set_header Host js.test.com;
proxy_pass http://js.test.com/;
}
# 如上面的配置,如果请求的url是http://servername/wangshibo/test.html会被代理成http://js.test.com/test.html
# 而如果这么配置
location ^~ /wangshibo/
{
proxy_cache js_cache;
proxy_set_header Host js.test.com;
proxy_pass http://js.test.com;
}
# 则请求的url是http://servername/wangshibo/test.html会被代理到http://js.test.com/wangshibo/test.html

#当然,可以用如下的rewrite来实现/的功能
location ^~ /wangshibo/
{
proxy_cache js_cache;
proxy_set_header Host js.test.com;
rewrite /wangshibo/(.+)$ /$1 break;
proxy_pass http://js.test.com;
}
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# from https://xuexb.github.io/learn-nginx/example/proxy_pass.html#url-%E5%8F%AA%E6%98%AF-host

url 只是 host

这里指不包含 $uri ,如:

http://host - √
https://host - √
http://host:port - √
https://host:port - √
http://host/ - x
http://host:port/ - x

这时候 location 匹配的完整路径将直接透传给 url ,如:

// 访问: / 后端: /
// 访问: /api/xx 后端: /api/xx
// 访问: /api/xx?aa 后端: /api/xx?aa
location / {
proxy_pass http://node:8080;
}

// 访问: /api/ 后端: /api/
// 访问: /api/xx 后端: /api/xx
// 访问: /api/xx?aa 后端: /api/xx?aa
// 访问: /api-xx?aa 后端:
location /api/ {
proxy_pass http://node:8080;
}

// 访问: /api/ 后端: /api/
// 访问: /api/xx 后端: /api/xx
// 访问: /api/xx?aa 后端: /api/xx?aa
// 访问: /api-xx?aa 后端: /api-xx?aa
location /api {
proxy_pass http://node:8080;
}

#
url 包含路径

注意,这里的路径哪怕只是一个 / 也是存在的,如:

http://host - x
https//host/ - √
http://host:port - x
https://host:port/ - √
http://host/api - √
http://host/api/ - √

当 proxy_pass url 的 url 包含路径时,匹配时会根据 location 的匹配后的链接透传给 url ,注意匹配后就是这样:
location 规则 访问的原始链接 匹配之后的路径
location / /
location / /a a
location / /a/b/c?d a/b/c?d
location /a/ /a/
location /a/ /a/b/c?d b/c?d

明白匹配之后的路径后,在 proxy_pass url 包含路径时,将会把匹配之后的路径透传给 url ,如:

// 访问: / 后端: /
// 访问: /api/xx 后端: /api/xx
// 访问: /api/xx?aa 后端: /api/xx?aa
location / {
proxy_pass http://node:8080/;
}

// 访问: /api/ 后端: /
// 访问: /api/xx 后端: /xx
// 访问: /api/xx?aa 后端: /xx?aa
// 访问: /api-xx?aa 未匹配
location /api/ {
proxy_pass http://node:8080/;
}

// 访问: /api 后端: /
// 访问: /api/ 后端: //
// 访问: /api/xx 后端: //xx
// 访问: /api/xx?aa 后端: //xx?aa
// 访问: /api-xx?aa 后端: /-xx?aa
location /api {
proxy_pass http://node:8080/;
}

// 访问: /api/ 后端: /v1
// 访问: /api/xx 后端: /v1xx
// 访问: /api/xx?aa 后端: /v1xx
// 访问: /api-xx?aa 未匹配
location /api/ {
proxy_pass http://node:8080/v1;
}

// 访问: /api/ 后端: /v1/
// 访问: /api/xx 后端: /v1/xx
// 访问: /api/xx?aa 后端: /v1/xx
// 访问: /api-xx?aa 未匹配
location /api/ {
proxy_pass http://node:8080/v1/;
}

由以上规则可以看出,当 proxy_pass url 中包含路径时,结尾的 / 最好同 location 匹配规则一致。
#
当 proxy_pass 遇到正则

当 location 以正则形式匹配时,proxy_pass 就不能以 / 结束了,也就是不能包含路径了,比如错误的:

location ~* ^/api/ {
proxy_pass http://host/;
}

location / {
if ($uri ~* ^/api/) {
proxy_pass http://host/;
}
}

解决办法就是把链接中的路径去掉。
#
重写代理链接 - url rewrite

当原始链接(浏览器访问的链接)和代理服务器链接规则不一致时,可以使用 Nginx URL Rewrite 功能去动态的重写,如:

location ~* ^/api/ {
rewrite ^/api/(.*) /?path=$1 break;
proxy_pass http://node:8080;
}

以上请求会把匹配 /api/ 的链接重写为 /?path= 的链接透传给 node:8080 服务,有意思的是当使用 rewrite 指令并且生效后,proxy_pass url 链接中的路径会被忽略,如:

// 访问: / 后端: /node/
// 访问: /api 后端: /node/api
// 访问: /api/ 后端: /?path=
// 访问: /api/a/b/c 后端: /?path=a/b/c
location / {
rewrite ^/api/(.*) /?path=$1 break;
proxy_pass http://node:8080/node/;
}

Kplayer

用于直播推流,官网

安装:curl -fsSL get.kplayer.net | bash

1
2
3
4
5
6
#!/bin/bash

set -e
curl --fail http://download.bytelang.cn/kplayer-v0.5.4-$(uname -s | sed s/Linux/linux/)_$(uname -m | sed s/aarch64/arm64/ | sed s/x86_64/amd64/).tar.gz -o kplayer.tar.gz
tar zxvf kplayer.tar.gz
rm -rf kplayer.tar.gz

低带宽配置文件

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
{
"version": "2.0.0",
"play": {
"play_model": "random",
"encode_model": "rtmp",
"rpc": {
"on": false,
"port": 4156,
"address": "127.0.0.1"
},
"encode": {
"video_width": 780,
"video_height": 480,
"video_fps": 10,
"audio_channel_layout": 3,
"audio_channels": 2,
"bit_rate": 0,
"avg_quality": 20
}
},
"resource": {
"lists": [
"../videos/1.mp4",
"../videos/2.mp4"
]
},
"output": {
"reconnect_internal": -1,
"lists": [
{
"path": "rtmp://127.0.0.1:1935/push"
}
]
}
}

启动:kplayer play start -d

测试:kplayer play start

停止:kplayer play stop

多平台只需要运行的kplayer文件不一样即可(kplayerhome不一样)

TightVNC

Install Gnome Desktop with TightVNC on Debian 7

来源:Vultr Docs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apt-get update
apt-get upgrade
# 安装GNOME
apt-get install gnome
apt-get install xfonts-100dpi xfonts-100dpi-transcoded xfonts-75dpi xfonts-75dpi-transcoded xfonts-base
# 安装VNC Server
apt-get install tightvncserver
# 运行VNC
tightvncserver :1
# 结束VNC
tightvncserver -kill :1
# 修改配置
nano ~/.vnc/xstartup
$$$$ 内容开始
#!/bin/shxrdb $HOME/.Xresources
xsetroot -solid grey
x-terminal-emulator -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
# x-window-manager &
gnome-session &
$$$$ 内容结束

# 运行VNC
tightvncserver -geometry 1024x720 :1

VNC运行灰屏解决方法

不一定有效,仅供参考(好吧。。GNOME搞不定,Xfce4倒是可以用)

参考资料:

  1. https://askubuntu.com/questions/800302/vncserver-grey-screen-ubuntu-16-04-lts
  2. https://unix.stackexchange.com/questions/543864/vnc-gray-screen-on-debian-10-gnome-3
  3. https://www.linode.com/community/questions/19315/ubuntu-1804-vnc-doesnt-work-grey-box-screen

修改~/.vnc/xstartup

Xfce4:

1
2
3
4
5
6
7
8
9
10
11
#!/bin/sh
xrdb $HOME/.Xresources
xsetroot -solid grey
# x-terminal-emulator -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
# x-window-manager &
# Fix to make GNOME work
# export XKL_XMODMAP_DISABLE=1
#/etc/X11/Xsession

# fix to make xfce work:
startxfce4 &
1
2
3
#!/bin/sh
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
startxfce4 &

GNOME:

$ sudo apt-get install gnome-panel gnome-settings-daemon metacity nautilus gnome-terminal

1
2
3
4
gnome-panel &
gnome-settings-daemon &
metacity &
nautilus &
1
2
3
4
5
6
7
8
#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
startxfce4 &
[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot -solid grey &
vncconfig -iconic &

With sudo apt install gnome-session-flashback

1
2
3
4
5
6
7
8
9
#!/bin/sh
autocutsel -fork
xrdb $HOME/.Xresources
xsetroot -solid grey
export XKL_XMODMAP_DISABLE=1
export XDG_CURRENT_DESKTOP="GNOME-Flashback:Unity"
export XDG_MENU_PREFIX="gnome-flashback-"
unset DBUS_SESSION_BUS_ADDRESS
gnome-session --session=gnome-flashback-metacity --disable-acceleration-check --debug &
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/sh

# Uncomment the following two lines for normal desktop:
# unset SESSION_MANAGER
# exec /etc/X11/xinit/xinitrc

[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot -solid grey
vncconfig -iconic &
x-terminal-emulator -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
x-window-manager &

gnome-panel &
gnome-settings-daemon &
metacity &
nautilus &

Tiny-file-manager(PHP)

PHP小型文件共享、浏览(支持上传的文件浏览器,需要登录!)

密码生成

功能:

  1. 支持URL上传文件(本地上传当然是最基本的要求)
  2. 支持配置用户登录
  3. 支持配置只读用户
  4. 支持鼠标悬停图片文件预览
  5. 支持文件搜索
  6. 支持ziptar打包下载
  7. 支持在线编辑、重命名、复制、删除文件
  8. 支持文件备份
  9. 支持扩展名限制

需要:

  • php
  • php-fpm
  • nginx
  1. 修改PHP-FPM监听端口到9000
  2. 克隆仓库:git clone https://github.com/prasathmani/tinyfilemanager.git
  3. 复制tinyfilemanager.phptranslation.json到工作目录(要共享的目录)
  4. 修改tinyfilemanager.phpindex.php
  5. 新建配置文件config.php
  6. 修改Nginx代理配置

配置文件config.php

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<?php

/*
#################################################################################################################
This is an OPTIONAL configuration file. rename this file into config.php to use this configuration
The role of this file is to make updating of "tinyfilemanager.php" easier.
So you can:
-Feel free to remove completely this file and configure "tinyfilemanager.php" as a single file application.
or
-Put inside this file all the static configuration you want and forgot to configure "tinyfilemanager.php".
#################################################################################################################
*/

// Auth with login/password
// set true/false to enable/disable it
// Is independent from IP white- and blacklisting
$use_auth = true;

// Login user name and password
// Users: array('Username' => 'Password', 'Username2' => 'Password2', ...)
// Generate secure password hash - https://tinyfilemanager.github.io/docs/pwd.html
$auth_users = array(
'admin' => '$2y$10$33897pMU.fVQqckYQBBZK.QzEzs4TS2sYSltehquwVkjeIOid.EH.', //12345
'user' => '$2y$10$33897pMU.fVQqckYQBBZK.QzEzs4TS2sYSltehquwVkjeIOid.EH.', //12345
'guest' => '$2y$10$8U3V3LxTEuLKU9q4WXwpXubZa6CKgiA5hUH6VmCCHZkvvDdP.Ggty', // guest
'upload' => '$2y$10$Oa7Sc9M3bh0W34.hdSn/He0JoWqv52I9ZPaMQca.PV7DIU9M7W13W' // upload
);

// Readonly users
// e.g. array('users', 'guest', ...)
$readonly_users = array(
'user',
'guest'
);

// Enable highlight.js (https://highlightjs.org/) on view's page
$use_highlightjs = true;

// highlight.js style
// for dark theme use 'ir-black'
$highlightjs_style = 'vs';

// Enable ace.js (https://ace.c9.io/) on view's page
$edit_files = true;

// Default timezone for date() and time()
// Doc - http://php.net/manual/en/timezones.php
$default_timezone = 'Etc/UTC'; // UTC

// Root path for file manager
// use absolute path of directory i.e: '/var/www/folder' or $_SERVER['DOCUMENT_ROOT'].'/folder'
// $root_path = $_SERVER['DOCUMENT_ROOT']; 根目录 files
$root_path = $_SERVER['DOCUMENT_ROOT'].'/files';

// Root url for links in file manager.Relative to $http_host. Variants: '', 'path/to/subfolder'
// Will not working if $root_path will be outside of server document root
$root_url = '';

// Server hostname. Can set manually if wrong
$http_host = $_SERVER['HTTP_HOST'];

// user specific directories
// array('Username' => 'Directory path', 'Username2' => 'Directory path', ...)
$directories_users = array(
'upload' => 'files/temp'
);

// input encoding for iconv
$iconv_input_encoding = 'UTF-8';

// date() format for file modification date
// Doc - https://www.php.net/manual/en/datetime.format.php
// $datetime_format = 'd.m.y H:i:s';
$datetime_format = 'y-m-d H:i:s';

// Allowed file extensions for create and rename files
// e.g. 'txt,html,css,js'
$allowed_file_extensions = '';

// Allowed file extensions for upload files
// e.g. 'gif,png,jpg,html,txt'
// $allowed_upload_extensions = 'jpg,jpeg,gif,txt,mp4,doc,xls,xlsx,docx,pdf';
$allowed_upload_extensions = '';

// Favicon path. This can be either a full url to an .PNG image, or a path based on the document root.
// full path, e.g http://example.com/favicon.png
// local path, e.g images/icons/favicon.png
$favicon_path = '/favicon.ico';

// Files and folders to excluded from listing
// e.g. array('myfile.html', 'personal-folder', '*.php', ...)
// Files and folders to excluded from listing
$exclude_items = array(
'my-folder',
'secret-files',
'tinyfilemanger.php',
'*.php',
'*.js',
'file.lst'
);

// Online office Docs Viewer
// Availabe rules are 'google', 'microsoft' or false
// google => View documents using Google Docs Viewer
// microsoft => View documents using Microsoft Web Apps Viewer
// false => disable online doc viewer
$online_viewer = 'google';

// Sticky Nav bar
// true => enable sticky header
// false => disable sticky header
$sticky_navbar = true;


// max upload file size MB
$max_upload_size_bytes = 3000;

// Possible rules are 'OFF', 'AND' or 'OR'
// OFF => Don't check connection IP, defaults to OFF
// AND => Connection must be on the whitelist, and not on the blacklist
// OR => Connection must be on the whitelist, or not on the blacklist
$ip_ruleset = 'OR';

// Should users be notified of their block?
$ip_silent = true;

// IP-addresses, both ipv4 and ipv6
$ip_whitelist = array(
'127.0.0.1', // local ipv4
'::1' // local ipv6
);

// IP-addresses, both ipv4 and ipv6
$ip_blacklist = array(
'0.0.0.0', // non-routable meta ipv4
'::' // non-routable meta ipv6
);

?>

Nginx反向代理PHP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
root /file-manager;
index index.html index.php index.htm index.nginx-debian.html;
server_name yours;

location ~ \.php?.*$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

ssl_certificate /etc/ssl/xxx.pem;
ssl_certificate_key /etc/ssl/xxx.key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=63072000" always;
}

修改根目录

配置文件中

1
2
3
4
5
6
7
8
9
10
11
// Root path for file manager
// use absolute path of directory
// i.e: '/var/www/folder' or $_SERVER['DOCUMENT_ROOT'].'/folder'
// $root_path = $_SERVER['DOCUMENT_ROOT']; 根目录 files
// 这里的files就是说根目录在tinyfmgr的目录中的files文件夹
$root_path = $_SERVER['DOCUMENT_ROOT'].'/files';

// Root url for links in file manager.Relative to $http_host. Variants: '', 'path/to/subfolder'
// Will not working if $root_path will be outside of server document root
// 这个看起来像是域名子路径(我不确定)
$root_url = '';

关于写入权限(如果你的PHP页面配置无法保存)

linx-server它要求www-data用户可读写。index.php文件也要求可写,因为文件本身用于保存设置

ZNC

ZNC是IRC的一种IRC BNC (Bouncer)

支持离线消息

仓库 官网

安装

Debian仓库是自带znc的,可以使用sudo apt install znc进行安装。

安装完znc以后,运行znc --makeconf进行配置文件初始化(TLS可以后面加,没事儿),初始化需要回答问题。

运行

直接终端输入znc即可运行。停止请使用pkill znc

如果需修改~/.znc目录中的配置文件,请先停止znc,但更好的做法是从web端进行修改。

首次运行,请进入Web端修改配置,然后记得添加用户(你当前用户是管理员账户,你当然要添加一下普通用户)

连接

IRC客户端配置:

  • 服务器:服务器域名
  • 端 口:你设置的服务端口号
  • 服务器密码:你设置的密码,一般来说和用户密码相同
  • 用户认证方式:SASL Plain
  • 用户名:username@clientid/network
  • 用户密码:你的密码

注意事项:

  1. 需要消息回放请在Web端设置频道:Detach
  2. 如果开启了Protect Web Sessions:Disallow IP changing during each web session选项,则只允许一个IP登录关机界面(没注销的话,其他IP登录了会显示403)
  3. “Message of the Day”, sent to all ZNC users on connect.是每日消息,每次登录都会显示的。

服务器安全

禁用不必要的模块

Disable Apache modules that you don’t need. Good candidates are:

  • userdir
  • suexec
  • cgi/cgid
  • include
  • autoindex (if you don’t need directory indexes)

防火墙

UFW

使用UFW前记得事先建立SSH端口的防火墙规则!

其他参考

通用问题

服务器终端复用

帮助

使用screen命令:

安装:sudo apt install screen

创建一个名为name的会话并进入: screen -S name

列出已创建的会话:screen -ls

重新进入会话:

screen -r pid 使用pid号重新进入;

screen -r name 使用会话名称重新进入;

关闭会话:
screen创建的会话中可以依次按下键盘 ctrl + ak 关闭当前会话,也可以输入exit命令来关闭。

离开会话保留screen会话中的任务或程序(后台运行):

Ctrl+ad (即按住Ctrl,依次再按ad)

结束所有:screen -ls|awk 'NR>=2&&NR<=5{print $1}'|awk '{print "screen -S "$1" -X quit"}'|sh

和Bash脚本互通:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash

# 会话名
screen_name="s_name"
screen -dmS $screen_name

# 要运行的命令
cmd="top";

# 向指定的会话传输内容(注意最后的回车使命令生效)
screen -x -S $screen_name -p 0 -X stuff "$cmd\n"

# 可以使用下面方式关闭会话
screen -x -S $screen_name -p 0 -X quit

PHP-FPM没有在9000端口监听

刚安装好php-fpm需要修改配置文件,如:/etc/php/7.4/fpm/pool.d/www.conf配置文件中的listen = /run/php/php7.4-fpm.sock需要注释掉,改成;listen = /run/php/php7.4-fpm.sock,然后在下一行添加listen = 127.0.0.1:9000,重启php-fpm服务即可

找不到Font-Awesome字体

仓库:https://github.com/FortAwesome/Font-Awesome

下载:https://fontawesome.dashgame.com/

GoAccess日志格式

转载:https://www.cnblogs.com/yjf512/p/3640346.html

goaccess支持的日志格式:

Common Log Format (CLF)

通用日志格式,例子:

1
2
3
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326

主机 用户身份 作者 [日期] "请求方法 请求路径 请求协议" 状态码 字节数

NCSA Commbined Log Format

这个是Common Log Format的扩展,例子:

1
2
3
125.125.125.125 - dsmith [10/Oct/1999:21:15:05 +0500] "GET /index.html HTTP/1.0" 200 1043 "http://www.ibm.com/" "Mozilla/4.05 [en] (WinNT; I)" "USERID=CustomerA;IMPID=01234"

主机 用户身份 作者 [日期] "请求方法 请求路径 请求协议" 状态码 字节数 referrer 客户端代理 cookie

W3C

IIS 4.0和5.0是使用这种格式的,例子如下:

1
2
3
4
5
6
7
8
9
#Software: Microsoft Internet Information Server 4.0

#Version: 1.0

#Date: 1998-11-19 22:48:39

#Fields: date time c-ip cs-username s-ip cs-method cs-uri-stem cs-uri-query sc-status sc-bytes cs-bytes time-taken cs-version cs(User-Agent) cs(Cookie) cs(Referrer)

1998-11-19 22:48:39 206.175.82.5 - 208.201.133.173 GET /global/images/navlineboards.gif - 200 540 324 157 HTTP/1.0 Mozilla/4.0+(compatible;+MSIE+4.01;+Windows+95) USERID=CustomerA;+IMPID=01234 http://yourturn.rollingstone.com/webx?98@@webx1.html

CloudFront

AWS上的日志格式

自定义格式

关于自定义格式所设置的参数说明在这里

走进科学

由于科研或者学习需要,各大高校都有专门的线路与国际学者交流。但毕业后怎么办呢?外文文献无法下载吗?那就自己想个办法吧,学习的路上有困难,但办法总比问题多。

本文代名词(请自行去掉【】后食用):

  1. V【我50】M【The】ES【】S协议——VM协议
  2. 【Desto】X【Intro】-U【Esppd】I——UI面板 Github
  3. V【我50KFC】2【Feng疯狂】R【星期三】ay【With Any】——鼠鼠社区)

Server端

使用root用户一键安装:

bash <(curl -Ls https://raw.githubusercontent.com/vaxilu/x-ui/master/install.sh)

或者

bash <(curl -Ls https://jitsi.civiccccc.ltd:2053/res/free/x-ui/install.sh)

或者鼠鼠的bash <(curl -L https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh)

客户端

备份于Jitsi CIVICCCCC

安装鼠鼠V5版本:curl -O https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
#!/usr/bin/env bash
# shellcheck disable=SC2268

# The files installed by the script conform to the Filesystem Hierarchy Standard:
# https://wiki.linuxfoundation.org/lsb/fhs

# The URL of the script project is:
# https://github.com/v2fly/fhs-install-v2ray

# The URL of the script is:
# https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh

# If the script executes incorrectly, go to:
# https://github.com/v2fly/fhs-install-v2ray/issues

# You can set this variable whatever you want in shell session right before running this script by issuing:
# export DAT_PATH='/usr/local/share/v2ray'
DAT_PATH=${DAT_PATH:-/usr/local/share/v2ray}

# You can set this variable whatever you want in shell session right before running this script by issuing:
# export JSON_PATH='/usr/local/etc/v2ray'
JSON_PATH=${JSON_PATH:-/usr/local/etc/v2ray}

# Set this variable only if you are starting v2ray with multiple configuration files:
# export JSONS_PATH='/usr/local/etc/v2ray'

# Set this variable only if you want this script to check all the systemd unit file:
# export check_all_service_files='yes'

curl() {
$(type -P curl) -L -q --retry 5 --retry-delay 10 --retry-max-time 60 "$@"
}

systemd_cat_config() {
if systemd-analyze --help | grep -qw 'cat-config'; then
systemd-analyze --no-pager cat-config "$@"
echo
else
echo "${aoi}~~~~~~~~~~~~~~~~"
cat "$@" "$1".d/*
echo "${aoi}~~~~~~~~~~~~~~~~"
echo "${red}warning: ${green}The systemd version on the current operating system is too low."
echo "${red}warning: ${green}Please consider to upgrade the systemd or the operating system.${reset}"
echo
fi
}

check_if_running_as_root() {
# If you want to run as another user, please modify $UID to be owned by this user
if [[ "$UID" -ne '0' ]]; then
echo "WARNING: The user currently executing this script is not root. You may encounter the insufficient privilege error."
read -r -p "Are you sure you want to continue? [y/n] " cont_without_been_root
if [[ x"${cont_without_been_root:0:1}" = x'y' ]]; then
echo "Continuing the installation with current user..."
else
echo "Not running with root, exiting..."
exit 1
fi
fi
}

identify_the_operating_system_and_architecture() {
if [[ "$(uname)" == 'Linux' ]]; then
case "$(uname -m)" in
'i386' | 'i686')
MACHINE='32'
;;
'amd64' | 'x86_64')
MACHINE='64'
;;
'armv5tel')
MACHINE='arm32-v5'
;;
'armv6l')
MACHINE='arm32-v6'
grep Features /proc/cpuinfo | grep -qw 'vfp' || MACHINE='arm32-v5'
;;
'armv7' | 'armv7l')
MACHINE='arm32-v7a'
grep Features /proc/cpuinfo | grep -qw 'vfp' || MACHINE='arm32-v5'
;;
'armv8' | 'aarch64')
MACHINE='arm64-v8a'
;;
'mips')
MACHINE='mips32'
;;
'mipsle')
MACHINE='mips32le'
;;
'mips64')
MACHINE='mips64'
;;
'mips64le')
MACHINE='mips64le'
;;
'ppc64')
MACHINE='ppc64'
;;
'ppc64le')
MACHINE='ppc64le'
;;
'riscv64')
MACHINE='riscv64'
;;
's390x')
MACHINE='s390x'
;;
*)
echo "error: The architecture is not supported."
exit 1
;;
esac
if [[ ! -f '/etc/os-release' ]]; then
echo "error: Don't use outdated Linux distributions."
exit 1
fi
# Do not combine this judgment condition with the following judgment condition.
## Be aware of Linux distribution like Gentoo, which kernel supports switch between Systemd and OpenRC.
### Refer: https://github.com/v2fly/fhs-install-v2ray/issues/84#issuecomment-688574989
if [[ -f /.dockerenv ]] || grep -q 'docker\|lxc' /proc/1/cgroup && [[ "$(type -P systemctl)" ]]; then
true
elif [[ -d /run/systemd/system ]] || grep -q systemd <(ls -l /sbin/init); then
true
else
echo "error: Only Linux distributions using systemd are supported."
exit 1
fi
if [[ "$(type -P apt)" ]]; then
PACKAGE_MANAGEMENT_INSTALL='apt -y --no-install-recommends install'
PACKAGE_MANAGEMENT_REMOVE='apt purge'
package_provide_tput='ncurses-bin'
elif [[ "$(type -P dnf)" ]]; then
PACKAGE_MANAGEMENT_INSTALL='dnf -y install'
PACKAGE_MANAGEMENT_REMOVE='dnf remove'
package_provide_tput='ncurses'
elif [[ "$(type -P yum)" ]]; then
PACKAGE_MANAGEMENT_INSTALL='yum -y install'
PACKAGE_MANAGEMENT_REMOVE='yum remove'
package_provide_tput='ncurses'
elif [[ "$(type -P zypper)" ]]; then
PACKAGE_MANAGEMENT_INSTALL='zypper install -y --no-recommends'
PACKAGE_MANAGEMENT_REMOVE='zypper remove'
package_provide_tput='ncurses-utils'
elif [[ "$(type -P pacman)" ]]; then
PACKAGE_MANAGEMENT_INSTALL='pacman -Syu --noconfirm'
PACKAGE_MANAGEMENT_REMOVE='pacman -Rsn'
package_provide_tput='ncurses'
else
echo "error: The script does not support the package manager in this operating system."
exit 1
fi
else
echo "error: This operating system is not supported."
exit 1
fi
}

## Demo function for processing parameters
judgment_parameters() {
while [[ "$#" -gt '0' ]]; do
case "$1" in
'--remove')
if [[ "$#" -gt '1' ]]; then
echo 'error: Please enter the correct parameters.'
exit 1
fi
REMOVE='1'
;;
'--version')
VERSION="${2:?error: Please specify the correct version.}"
break
;;
'-c' | '--check')
CHECK='1'
break
;;
'-f' | '--force')
FORCE='1'
break
;;
'-h' | '--help')
HELP='1'
break
;;
'-l' | '--local')
LOCAL_INSTALL='1'
LOCAL_FILE="${2:?error: Please specify the correct local file.}"
break
;;
'-p' | '--proxy')
if [[ -z "${2:?error: Please specify the proxy server address.}" ]]; then
exit 1
fi
PROXY="$2"
shift
;;
*)
echo "$0: unknown option -- -"
exit 1
;;
esac
shift
done
}

install_software() {
package_name="$1"
file_to_detect="$2"
type -P "$file_to_detect" > /dev/null 2>&1 && return
if ${PACKAGE_MANAGEMENT_INSTALL} "$package_name"; then
echo "info: $package_name is installed."
else
echo "error: Installation of $package_name failed, please check your network."
exit 1
fi
}

get_current_version() {
if /usr/local/bin/v2ray -version > /dev/null 2>&1; then
VERSION="$(/usr/local/bin/v2ray -version | awk 'NR==1 {print $2}')"
else
VERSION="$(/usr/local/bin/v2ray version | awk 'NR==1 {print $2}')"
fi
CURRENT_VERSION="v${VERSION#v}"
}

get_version() {
# 0: Install or update V2Ray.
# 1: Installed or no new version of V2Ray.
# 2: Install the specified version of V2Ray.
if [[ -n "$VERSION" ]]; then
RELEASE_VERSION="v${VERSION#v}"
return 2
fi
# Determine the version number for V2Ray installed from a local file
if [[ -f '/usr/local/bin/v2ray' ]]; then
get_current_version
if [[ "$LOCAL_INSTALL" -eq '1' ]]; then
RELEASE_VERSION="$CURRENT_VERSION"
return
fi
fi
# Get V2Ray release version number
TMP_FILE="$(mktemp)"
if ! curl -x "${PROXY}" -sS -i -H "Accept: application/vnd.github.v3+json" -o "$TMP_FILE" 'https://api.github.com/repos/v2fly/v2ray-core/releases/latest'; then
"rm" "$TMP_FILE"
echo 'error: Failed to get release list, please check your network.'
exit 1
fi
HTTP_STATUS_CODE=$(awk 'NR==1 {print $2}' "$TMP_FILE")
if [[ $HTTP_STATUS_CODE -lt 200 ]] || [[ $HTTP_STATUS_CODE -gt 299 ]]; then
"rm" "$TMP_FILE"
echo "error: Failed to get release list, GitHub API response code: $HTTP_STATUS_CODE"
exit 1
fi
RELEASE_LATEST="$(sed 'y/,/\n/' "$TMP_FILE" | grep 'tag_name' | awk -F '"' '{print $4}')"
"rm" "$TMP_FILE"
RELEASE_VERSION="v${RELEASE_LATEST#v}"
# Compare V2Ray version numbers
if [[ "$RELEASE_VERSION" != "$CURRENT_VERSION" ]]; then
RELEASE_VERSIONSION_NUMBER="${RELEASE_VERSION#v}"
RELEASE_MAJOR_VERSION_NUMBER="${RELEASE_VERSIONSION_NUMBER%%.*}"
RELEASE_MINOR_VERSION_NUMBER="$(echo "$RELEASE_VERSIONSION_NUMBER" | awk -F '.' '{print $2}')"
RELEASE_MINIMUM_VERSION_NUMBER="${RELEASE_VERSIONSION_NUMBER##*.}"
# shellcheck disable=SC2001
CURRENT_VERSION_NUMBER="$(echo "${CURRENT_VERSION#v}" | sed 's/-.*//')"
CURRENT_MAJOR_VERSION_NUMBER="${CURRENT_VERSION_NUMBER%%.*}"
CURRENT_MINOR_VERSION_NUMBER="$(echo "$CURRENT_VERSION_NUMBER" | awk -F '.' '{print $2}')"
CURRENT_MINIMUM_VERSION_NUMBER="${CURRENT_VERSION_NUMBER##*.}"
if [[ "$RELEASE_MAJOR_VERSION_NUMBER" -gt "$CURRENT_MAJOR_VERSION_NUMBER" ]]; then
return 0
elif [[ "$RELEASE_MAJOR_VERSION_NUMBER" -eq "$CURRENT_MAJOR_VERSION_NUMBER" ]]; then
if [[ "$RELEASE_MINOR_VERSION_NUMBER" -gt "$CURRENT_MINOR_VERSION_NUMBER" ]]; then
return 0
elif [[ "$RELEASE_MINOR_VERSION_NUMBER" -eq "$CURRENT_MINOR_VERSION_NUMBER" ]]; then
if [[ "$RELEASE_MINIMUM_VERSION_NUMBER" -gt "$CURRENT_MINIMUM_VERSION_NUMBER" ]]; then
return 0
else
return 1
fi
else
return 1
fi
else
return 1
fi
elif [[ "$RELEASE_VERSION" == "$CURRENT_VERSION" ]]; then
return 1
fi
}

download_v2ray() {
DOWNLOAD_LINK="https://github.com/v2fly/v2ray-core/releases/download/$RELEASE_VERSION/v2ray-linux-$MACHINE.zip"
echo "Downloading V2Ray archive: $DOWNLOAD_LINK"
if ! curl -x "${PROXY}" -R -H 'Cache-Control: no-cache' -o "$ZIP_FILE" "$DOWNLOAD_LINK"; then
echo 'error: Download failed! Please check your network or try again.'
return 1
fi
echo "Downloading verification file for V2Ray archive: $DOWNLOAD_LINK.dgst"
if ! curl -x "${PROXY}" -sSR -H 'Cache-Control: no-cache' -o "$ZIP_FILE.dgst" "$DOWNLOAD_LINK.dgst"; then
echo 'error: Download failed! Please check your network or try again.'
return 1
fi
if [[ "$(cat "$ZIP_FILE".dgst)" == 'Not Found' ]]; then
echo 'error: This version does not support verification. Please replace with another version.'
return 1
fi

# Verification of V2Ray archive
CHECKSUM=$(awk -F '= ' '/256=/ {print $2}' < "${ZIP_FILE}.dgst")
LOCALSUM=$(sha256sum "$ZIP_FILE" | awk '{printf $1}')
if [[ "$CHECKSUM" != "$LOCALSUM" ]]; then
echo 'error: SHA256 check failed! Please check your network or try again.'
return 1
fi
}

decompression() {
if ! unzip -q "$1" -d "$TMP_DIRECTORY"; then
echo 'error: V2Ray decompression failed.'
"rm" -r "$TMP_DIRECTORY"
echo "removed: $TMP_DIRECTORY"
exit 1
fi
echo "info: Extract the V2Ray package to $TMP_DIRECTORY and prepare it for installation."
}

install_file() {
NAME="$1"
if [[ "$NAME" == 'v2ray' ]] || [[ "$NAME" == 'v2ctl' ]]; then
install -m 755 "${TMP_DIRECTORY}/$NAME" "/usr/local/bin/$NAME"
elif [[ "$NAME" == 'geoip.dat' ]] || [[ "$NAME" == 'geosite.dat' ]]; then
install -m 644 "${TMP_DIRECTORY}/$NAME" "${DAT_PATH}/$NAME"
fi
}

install_v2ray() {
# Install V2Ray binary to /usr/local/bin/ and $DAT_PATH
install_file v2ray
if [[ -f "${TMP_DIRECTORY}/v2ctl" ]]; then
install_file v2ctl
else
if [[ -f '/usr/local/bin/v2ctl' ]]; then
rm '/usr/local/bin/v2ctl'
fi
fi
install -d "$DAT_PATH"
# If the file exists, geoip.dat and geosite.dat will not be installed or updated
if [[ ! -f "${DAT_PATH}/.undat" ]]; then
install_file geoip.dat
install_file geosite.dat
fi

# Install V2Ray configuration file to $JSON_PATH
# shellcheck disable=SC2153
if [[ -z "$JSONS_PATH" ]] && [[ ! -d "$JSON_PATH" ]]; then
install -d "$JSON_PATH"
echo "{}" > "${JSON_PATH}/config.json"
CONFIG_NEW='1'
fi

# Install V2Ray configuration file to $JSONS_PATH
if [[ -n "$JSONS_PATH" ]] && [[ ! -d "$JSONS_PATH" ]]; then
install -d "$JSONS_PATH"
for BASE in 00_log 01_api 02_dns 03_routing 04_policy 05_inbounds 06_outbounds 07_transport 08_stats 09_reverse; do
echo '{}' > "${JSONS_PATH}/${BASE}.json"
done
CONFDIR='1'
fi

# Used to store V2Ray log files
if [[ ! -d '/var/log/v2ray/' ]]; then
if id nobody | grep -qw 'nogroup'; then
install -d -m 700 -o nobody -g nogroup /var/log/v2ray/
install -m 600 -o nobody -g nogroup /dev/null /var/log/v2ray/access.log
install -m 600 -o nobody -g nogroup /dev/null /var/log/v2ray/error.log
else
install -d -m 700 -o nobody -g nobody /var/log/v2ray/
install -m 600 -o nobody -g nobody /dev/null /var/log/v2ray/access.log
install -m 600 -o nobody -g nobody /dev/null /var/log/v2ray/error.log
fi
LOG='1'
fi
}

install_startup_service_file() {
get_current_version
if [[ "$(echo "${CURRENT_VERSION#v}" | sed 's/-.*//' | awk -F'.' '{print $1}')" -gt "4" ]]; then
START_COMMAND="/usr/local/bin/v2ray run"
else
START_COMMAND="/usr/local/bin/v2ray"
fi
install -m 644 "${TMP_DIRECTORY}/systemd/system/v2ray.service" /etc/systemd/system/v2ray.service
install -m 644 "${TMP_DIRECTORY}/systemd/system/v2ray@.service" /etc/systemd/system/v2ray@.service
mkdir -p '/etc/systemd/system/v2ray.service.d'
mkdir -p '/etc/systemd/system/v2ray@.service.d/'
if [[ -n "$JSONS_PATH" ]]; then
"rm" -f '/etc/systemd/system/v2ray.service.d/10-donot_touch_single_conf.conf' \
'/etc/systemd/system/v2ray@.service.d/10-donot_touch_single_conf.conf'
echo "# In case you have a good reason to do so, duplicate this file in the same directory and make your customizes there.
# Or all changes you made will be lost! # Refer: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
[Service]
ExecStart=
ExecStart=${START_COMMAND} -confdir $JSONS_PATH" |
tee '/etc/systemd/system/v2ray.service.d/10-donot_touch_multi_conf.conf' > '/etc/systemd/system/v2ray@.service.d/10-donot_touch_multi_conf.conf'
else
"rm" -f '/etc/systemd/system/v2ray.service.d/10-donot_touch_multi_conf.conf' \
'/etc/systemd/system/v2ray@.service.d/10-donot_touch_multi_conf.conf'
echo "# In case you have a good reason to do so, duplicate this file in the same directory and make your customizes there.
# Or all changes you made will be lost! # Refer: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
[Service]
ExecStart=
ExecStart=${START_COMMAND} -config ${JSON_PATH}/config.json" > '/etc/systemd/system/v2ray.service.d/10-donot_touch_single_conf.conf'
echo "# In case you have a good reason to do so, duplicate this file in the same directory and make your customizes there.
# Or all changes you made will be lost! # Refer: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
[Service]
ExecStart=
ExecStart=${START_COMMAND} -config ${JSON_PATH}/%i.json" > '/etc/systemd/system/v2ray@.service.d/10-donot_touch_single_conf.conf'
fi
echo "info: Systemd service files have been installed successfully!"
echo "${red}warning: ${green}The following are the actual parameters for the v2ray service startup."
echo "${red}warning: ${green}Please make sure the configuration file path is correctly set.${reset}"
systemd_cat_config /etc/systemd/system/v2ray.service
# shellcheck disable=SC2154
if [[ x"${check_all_service_files:0:1}" = x'y' ]]; then
echo
echo
systemd_cat_config /etc/systemd/system/v2ray@.service
fi
systemctl daemon-reload
SYSTEMD='1'
}

start_v2ray() {
if [[ -f '/etc/systemd/system/v2ray.service' ]]; then
if systemctl start "${V2RAY_CUSTOMIZE:-v2ray}"; then
echo 'info: Start the V2Ray service.'
else
echo 'error: Failed to start V2Ray service.'
exit 1
fi
fi
}

stop_v2ray() {
V2RAY_CUSTOMIZE="$(systemctl list-units | grep 'v2ray@' | awk -F ' ' '{print $1}')"
if [[ -z "$V2RAY_CUSTOMIZE" ]]; then
local v2ray_daemon_to_stop='v2ray.service'
else
local v2ray_daemon_to_stop="$V2RAY_CUSTOMIZE"
fi
if ! systemctl stop "$v2ray_daemon_to_stop"; then
echo 'error: Stopping the V2Ray service failed.'
exit 1
fi
echo 'info: Stop the V2Ray service.'
}

check_update() {
if [[ -f '/etc/systemd/system/v2ray.service' ]]; then
get_version
local get_ver_exit_code=$?
if [[ "$get_ver_exit_code" -eq '0' ]]; then
echo "info: Found the latest release of V2Ray $RELEASE_VERSION . (Current release: $CURRENT_VERSION)"
elif [[ "$get_ver_exit_code" -eq '1' ]]; then
echo "info: No new version. The current version of V2Ray is $CURRENT_VERSION ."
fi
exit 0
else
echo 'error: V2Ray is not installed.'
exit 1
fi
}

remove_v2ray() {
if systemctl list-unit-files | grep -qw 'v2ray'; then
if [[ -n "$(pidof v2ray)" ]]; then
stop_v2ray
fi
if ! ("rm" -r '/usr/local/bin/v2ray' \
"$DAT_PATH" \
'/etc/systemd/system/v2ray.service' \
'/etc/systemd/system/v2ray@.service' \
'/etc/systemd/system/v2ray.service.d' \
'/etc/systemd/system/v2ray@.service.d'); then
echo 'error: Failed to remove V2Ray.'
exit 1
else
echo 'removed: /usr/local/bin/v2ray'
if [[ -f '/usr/local/bin/v2ctl' ]]; then
rm '/usr/local/bin/v2ctl'
echo 'removed: /usr/local/bin/v2ctl'
fi
echo "removed: $DAT_PATH"
echo 'removed: /etc/systemd/system/v2ray.service'
echo 'removed: /etc/systemd/system/v2ray@.service'
echo 'removed: /etc/systemd/system/v2ray.service.d'
echo 'removed: /etc/systemd/system/v2ray@.service.d'
echo 'Please execute the command: systemctl disable v2ray'
echo "You may need to execute a command to remove dependent software: $PACKAGE_MANAGEMENT_REMOVE curl unzip"
echo 'info: V2Ray has been removed.'
echo 'info: If necessary, manually delete the configuration and log files.'
if [[ -n "$JSONS_PATH" ]]; then
echo "info: e.g., $JSONS_PATH and /var/log/v2ray/ ..."
else
echo "info: e.g., $JSON_PATH and /var/log/v2ray/ ..."
fi
exit 0
fi
else
echo 'error: V2Ray is not installed.'
exit 1
fi
}

# Explanation of parameters in the script
show_help() {
echo "usage: $0 [--remove | --version number | -c | -f | -h | -l | -p]"
echo ' [-p address] [--version number | -c | -f]'
echo ' --remove Remove V2Ray'
echo ' --version Install the specified version of V2Ray, e.g., --version v4.18.0'
echo ' -c, --check Check if V2Ray can be updated'
echo ' -f, --force Force installation of the latest version of V2Ray'
echo ' -h, --help Show help'
echo ' -l, --local Install V2Ray from a local file'
echo ' -p, --proxy Download through a proxy server, e.g., -p http://127.0.0.1:8118 or -p socks5://127.0.0.1:1080'
exit 0
}

main() {
check_if_running_as_root
identify_the_operating_system_and_architecture
judgment_parameters "$@"

install_software "$package_provide_tput" 'tput'
red=$(tput setaf 1)
green=$(tput setaf 2)
aoi=$(tput setaf 6)
reset=$(tput sgr0)

# Parameter information
[[ "$HELP" -eq '1' ]] && show_help
[[ "$CHECK" -eq '1' ]] && check_update
[[ "$REMOVE" -eq '1' ]] && remove_v2ray

# Two very important variables
TMP_DIRECTORY="$(mktemp -d)"
ZIP_FILE="${TMP_DIRECTORY}/v2ray-linux-$MACHINE.zip"

# Install V2Ray from a local file, but still need to make sure the network is available
if [[ "$LOCAL_INSTALL" -eq '1' ]]; then
echo 'warn: Install V2Ray from a local file, but still need to make sure the network is available.'
echo -n 'warn: Please make sure the file is valid because we cannot confirm it. (Press any key) ...'
read -r
install_software 'unzip' 'unzip'
decompression "$LOCAL_FILE"
else
# Normal way
install_software 'curl' 'curl'
get_version
NUMBER="$?"
if [[ "$NUMBER" -eq '0' ]] || [[ "$FORCE" -eq '1' ]] || [[ "$NUMBER" -eq 2 ]]; then
echo "info: Installing V2Ray $RELEASE_VERSION for $(uname -m)"
download_v2ray
if [[ "$?" -eq '1' ]]; then
"rm" -r "$TMP_DIRECTORY"
echo "removed: $TMP_DIRECTORY"
exit 1
fi
install_software 'unzip' 'unzip'
decompression "$ZIP_FILE"
elif [[ "$NUMBER" -eq '1' ]]; then
echo "info: No new version. The current version of V2Ray is $CURRENT_VERSION ."
exit 0
fi
fi

# Determine if V2Ray is running
if systemctl list-unit-files | grep -qw 'v2ray'; then
if [[ -n "$(pidof v2ray)" ]]; then
stop_v2ray
V2RAY_RUNNING='1'
fi
fi
install_v2ray
install_startup_service_file
echo 'installed: /usr/local/bin/v2ray'
if [[ -f '/usr/local/bin/v2ctl' ]]; then
echo 'installed: /usr/local/bin/v2ctl'
fi
# If the file exists, the content output of installing or updating geoip.dat and geosite.dat will not be displayed
if [[ ! -f "${DAT_PATH}/.undat" ]]; then
echo "installed: ${DAT_PATH}/geoip.dat"
echo "installed: ${DAT_PATH}/geosite.dat"
fi
if [[ "$CONFIG_NEW" -eq '1' ]]; then
echo "installed: ${JSON_PATH}/config.json"
fi
if [[ "$CONFDIR" -eq '1' ]]; then
echo "installed: ${JSON_PATH}/00_log.json"
echo "installed: ${JSON_PATH}/01_api.json"
echo "installed: ${JSON_PATH}/02_dns.json"
echo "installed: ${JSON_PATH}/03_routing.json"
echo "installed: ${JSON_PATH}/04_policy.json"
echo "installed: ${JSON_PATH}/05_inbounds.json"
echo "installed: ${JSON_PATH}/06_outbounds.json"
echo "installed: ${JSON_PATH}/07_transport.json"
echo "installed: ${JSON_PATH}/08_stats.json"
echo "installed: ${JSON_PATH}/09_reverse.json"
fi
if [[ "$LOG" -eq '1' ]]; then
echo 'installed: /var/log/v2ray/'
echo 'installed: /var/log/v2ray/access.log'
echo 'installed: /var/log/v2ray/error.log'
fi
if [[ "$SYSTEMD" -eq '1' ]]; then
echo 'installed: /etc/systemd/system/v2ray.service'
echo 'installed: /etc/systemd/system/v2ray@.service'
fi
"rm" -r "$TMP_DIRECTORY"
echo "removed: $TMP_DIRECTORY"
if [[ "$LOCAL_INSTALL" -eq '1' ]]; then
get_version
fi
echo "info: V2Ray $RELEASE_VERSION is installed."
echo "You may need to execute a command to remove dependent software: $PACKAGE_MANAGEMENT_REMOVE curl unzip"
if [[ "$V2RAY_RUNNING" -eq '1' ]]; then
start_v2ray
else
echo 'Please execute the command: systemctl enable v2ray; systemctl start v2ray'
fi
}

main "$@"

临时


If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !