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.
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.
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.
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).
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.
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.
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.
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.
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:
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.
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.
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
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.
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.
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'.
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".
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:
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.
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:
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 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连接下被禁用):
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.
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.
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.
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.
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.
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.
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'.
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:
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.
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.
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 .
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.
#### 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}
"机器人,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");
运行: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)
80/tcp for Web UI HTTP (really just to redirect, after uncommenting ENABLE_HTTP_REDIRECT=1in .env) 443/tcp for Web UI HTTPS 4443/tcp for RTP media over TCP 10000/udp for RTP media over UDP
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, ifnotdonot update.
# 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 { listen200 ssl http2; listen [::]:200 ssl http2; server_name jitsi.name;#域名 index index.html index.htm index.php; root /home/nginx/;#站点目录
#### 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_nofile4028;
# 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; #}
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.
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
/* ################################################################################################################# 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;
// 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'];
// 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 );
// 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 = '';
# 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'
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 }
# 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 }
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 !