更换omnifocus webdav同步服务器的悲催经历
背景:最近自己的omnifocus软件同步总有连接问题,查了下说明,发现omnifocus同步服务器可以被替换成其它支持webdav功能的服务器。看了看国内的webdav的服务,发现都要花钱。我这个人穷不拉几的不想再多一个续费项了。无巧不巧的我手头正好有个阿里云的CentOS系统。上面就跑着个GitLab用来给我存点无关紧要的东西。所以我决定试试自己搞一个webdav试试……嗯,这就是一切噩梦源头的开始……
编译webdav功能的nginx
在http服务上,我选择了nginx,没有去选用apache,主要是由于我以前在系统上部署过nginx。nginx想要支持webdav功能,需要在编译时添加扩展dav插件。所以需要自己下载nginx源码和dav组件源码再一起编译一个混血版。
名称 | 版本 | 下载链接 |
---|---|---|
nginx | 1.20.1 | https://nginx.org/en/download.html |
nginx-dav-ext-module | N/A | https://gitee.com/mirrors/nginx-dav-ext-module?_from=gitee_search https://github.com/arut/nginx-dav-ext-module |
- 提供了两个nginx-dav-ext-module的下载链接,github我死活下载不下来,幸好Gitee找到了镜像版本,没有让我的想法死在greatwall下,赞Gitee
- nginx也要注意一下版本,我之前是用的1.12.2版本(我过去部署在服务器上的版本,本来想犯个懒不下nginx的源码了,可编译总是失败。浪费了4根烟后,查了下dav插件的说明,才知道最低支持版本要>=1.13.4,我这运气真好……
两部分代码下载下来,nginx我下下来的是.tar.gz结尾的压缩格式,需要先解压
[root@AliS _Soft]# tar zxvf nginx-1.20.1.tar.gz
[root@AliS _Soft]# ls -ld nginx*
-rw-r--r-- 1 root root 981687 Jan 5 2018 nginx-1.12.2.tar.gz
drwxr-xr-x 9 sftpusers www 4096 Jul 10 10:43 nginx-1.20.1
-rw-r--r-- 1 root root 1061461 May 25 23:34 nginx-1.20.1.tar.gz
drwxr-xr-x 3 root root 4096 Jul 9 21:03 nginx-dav-ext-module
请忽略掉那个无知的nginx-1.12.2的文件……
由于我编译的nginx除了支持webdav,还需要支持我系统上原来的gitlab。gitlab在安装的时候自带一个内嵌的nginx,需要用我新编译的私有nginx替换掉,所以先查看一下gitlab内嵌的nginx带的参数
[root@AliS _Soft]# /opt/gitlab/embedded/sbin/nginx -V
nginx version: nginx/1.12.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC)
built with OpenSSL 1.0.2l 25 May 2017
TLS SNI support enabled
configure arguments: --prefix=/opt/gitlab/embedded --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_v2_module --with-http_realip_module --with-ipv6 --with-debug --with-ld-opt=-L/opt/gitlab/embedded/lib --with-cc-opt='-L/opt/gitlab/embedded/lib -I/opt/gitlab/embedded/include'
打开一个自己必须喜欢的文本文档工具,我用的VSCode,眉飞色舞的写下一个编译用的config。其实就是写个头儿和加个dav的参数,中间的参数大部分都是拷贝的gitlab里面的configure arguments的段……
./configure \
--prefix=/usr/local/nginx-1.20.1 \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-http_v2_module \
--with-http_realip_module \
--with-debug \
--with-ld-opt='-L /opt/gitlab/embedded/lib' \
--with-cc-opt='-L /opt/gitlab/embedded/lib -I /opt/gitlab/embedded/include' \
--with-http_dav_module --add-module='/root/_Soft/nginx-dav-ext-module/nginx-dav-ext-module'
参数 | 说明 |
---|---|
–prefix | 指定编译后的nginx目录。我指定了一个和gitlab的nginx不同的目录,这样万一玩砸了,至少我还有机会用老的nginx把我的gitlab服务拉起来,不会死的很惨。 |
–with-* | 都是一些nginx的模块,为了同时支持gitlab,我就原封不动的C/P了它的参数。 一定要把 --with-http_dav_module --add-module=’/root/_Soft/nginx-dav-ext-module/nginx-dav-ext-module’加进来,这个路径就是下的那个模块的存放路径 还有别问我为啥有两级nginx-dav-ext-module,git同步的,结果忘记它自己很聪明会自己建目录,搞技术太难了…… |
–add-module | 指定外部插件源代码的目录 |
\ | 这东西是一行写不下用来换行用的 |
之后就是进入到nginx源码目录去运行编译了。注意是nginx的源码目录,别进城nginx-dav的插件目录了
[root@AliS _Soft]# cd nginx-1.20.1
[root@AliS nginx-1.20.1]# ls
CHANGES CHANGES.ru LICENSE Makefile README auto conf configure contrib html man objs src
先配置一下要编译的内容,从你喜欢的文本工具中复制刚才已经写好的命令
[root@AliS nginx-1.20.1]# ./configure \
> --prefix=/usr/local/nginx-1.20.1 \
> --with-http_ssl_module \
> --with-http_stub_status_module \
> --with-http_gzip_static_module \
> --with-http_v2_module \
> --with-http_realip_module \
> --with-debug \
> --with-ld-opt='-L /opt/gitlab/embedded/lib' \
> --with-cc-opt='-L /opt/gitlab/embedded/lib -I /opt/gitlab/embedded/include' \
> --with-http_dav_module --add-module='/root/_Soft/nginx-dav-ext-module/nginx-dav-ext-module'
回车自己去敲吧,反正最后提示成功就是成功了。提示别的就是写错了……
之后就是编译了
[root@AliS nginx-1.20.1]# make & make install
后面就是等着编译log去刷屏了,刷完了就好了,不用搭理它。我说个小插曲轻松一下。
在我四处百度编译命令的时候,打开的第一个文章(利用Nginx WebDAV搭建自己的网盘),里面的编译命令是这么写的
# make -j8
我心说哥们你make就make吧,怎么还骂人呢!后来一查才知道,-j 是指定用多少个CPU core并行编译,可以增加编译速度的。丢人~
后来我还特意试了试用不同核数去编译,其实一个nginx用一个核也编译不了多会儿的,j8不j8的问题都不大嘿……
看完那段差不多编译也就结束了,一个属于自己的nginx应该已经静静的躺在你编译配置指定的目录里了(我的在/usr/local/nginx-1.20.1)
[root@AliS local]# ln -s nginx-1.20.1 nginx
[root@AliS local]# ls -ld nginx*
lrwxrwxrwx 1 root root 12 Jul 10 10:46 nginx -> nginx-1.20.1
drwxr-xr-x 11 root root 4096 Sep 29 2018 nginx-1.12.2
drwxr-xr-x 12 root root 4096 Jul 11 21:33 nginx-1.20.1
[root@AliS local]# pwd
/usr/local
[root@AliS local]#
为了图方便,我做了个nginx的软连接仍在相同的目录了,这样玩砸了回滚会简单点,只切换个软连接指向就好了,省的把目录内外搞得乌烟瘴气的
用当前的私有nginx替换gitlab的内嵌nginx
其实没有gitlab影响可以跳过这一章的,都去抽根烟吃个果盘儿歇会儿吧~
文件 | 说明 |
---|---|
/etc/gitlab/gitlab.rb | gitlab配置文件 |
/var/opt/gitlab/nginx/conf/ | gitlab内嵌nginx配置文件目录 |
/usr/local/nginx/conf | 私有nginx配置文件目录 |
/usr/local/nginx/conf/vhosts | 私有nginx vhosts配置目录 |
端口 | 端口定义 |
---|---|
8091 | 私有nginx提供的gitlab对外访问端口 |
8891 | 私有nginx提供的gitlab_workhorse内部访问端口 |
其实这步说难不难,主要是不要马虎大意。用vi或者喜欢的编辑器打开配置文件一顿脑残编辑就好了
另外,想着先拷贝一份当前的配置文件到别的目录做个备份,备份别放在/etc目录下就行。
先搞一下/etc/gitlab/gitlab.rb,这个是gitlab的配置文件,下面中的#是文件注释,我习惯于拷贝出来一行原参数再取消注释进行修改。
# external_url 'http://gitlab.example.com'
external_url 'http://50.50.50.50:8091' #改成自己gitlab的真实访问的地址就行
# nginx['enable'] = true
nginx['enable'] = false #关闭gitlab内置的nginx功能
# gitlab_workhorse['listen_network'] = "unix"
gitlab_workhorse['listen_network'] = "tcp" #更改workhorse的传输方式从socket到TCP
# gitlab_workhorse['listen_addr'] = "/var/opt/gitlab/gitlab-workhorse/socket"
gitlab_workhorse['listen_addr'] = "127.0.0.1:8891" #我设置了8891端口,其实找个别的没用的端口就行
# gitlab_rails['trusted_proxies'] = []
gitlab_rails['trusted_proxies'] = ['50.50.50.50'] #把gitlab的对外地址加到rail的信任列表里
# web_server['external_users'] = []
web_server['external_users'] = ['root', 'nobody'] #我一劳永逸的都加进去了
编辑完gitlab.rb文件,还需要把gitlab原先内嵌的nginx提供的服务添加到自己私有的nginx里面
[root@AliS ~]# cd /var/opt/gitlab/nginx/conf/
[root@AliS conf]# ls
gitlab-http.conf nginx-status.conf nginx.conf
上面是我的gitlab内嵌nginx放配置的地方,nginx.conf是主配置文件,其他两个都在nginx.conf中被引用了,所以本着能懒就懒的原则,我决定回头把nginx.conf的内容合并到我的私有nginx配置里就好,引用的那两个文件就还放在这里不动了。
传说中nginx可以使用vhosts功能分离配置文件,为了简便,我直接把gitlab的内容拷贝成一个vhosts配置文件,依旧防止我手残的把主配置文件修改的乱七八糟
先在私有的nginx conf目录建一个vhosts的文件夹
[root@AliS conf]# pwd
/usr/local/nginx/conf
[root@AliS conf]# mkdir vhosts
然后在conf目录修改nginx.conf文件,添加要引用vhosts目录的文件
user root gitlab-www;
...
http {
...
include vhosts/*.conf;
}
修改ngnix.conf的时候,要看一下开头的user定义,是用的哪个用户来假装运行nginx的,这个用户要包含在gitlab.rb的下列配置中(我是用的root啦)
web_server[‘external_users’] = [‘root’, ‘nobody’]
之后我就是在vhosts目录新建了一个gitlab.conf,再大刀阔斧的把gitlab里面的nginx配置拷贝了过来。拷贝过来后要注意两点
- 有些配置参数已经在nginx.conf定义过了,需要在gitlab中注释掉,防止重复定义
- 因为刚刚在gitlab.rb中把gitlab_workhorse给定义成TCP的形式了,所以要给这个workhorse建立一个虚拟server去提供http服务,让workhorse的数据可以流转
server {
listen 8091;
server_name localhost;
location / {
root html;
index index.html index.htm;
proxy_pass http://127.0.0.1:8891;
}
}
这里定义的8091端口,是对外访问gitlab的地址,之后获得的数据会被转发给http://127.0.0.1:8891。所以这个8891的端口要和gitlab.rb中修改的配置一致,不然gitlab_workhorse就接收不到数据了,页面也会报告很难搞得504 error……(别问我怎么知道的,8091,8891,8091,8891当初定义的太像了,加上我眼睛又近视,这个错误白白浪费了我5根烟!)
gitlab_workhorse[‘listen_addr’] = “127.0.0.1:8891”
下面上整个配置文件
# gitlab config
# The orignal git lab nginx is /opt/gitlab/embedded/sbin/nginx -p /var/opt/gitlab/nginx
log_format gitlab_access '$remote_addr - $remote_user [$time_local] "$request_method $filtered_request_uri $server_protocol" $status $body_bytes_sent "$filtered_http_referer" "$http_user_agent"';
log_format gitlab_mattermost_access '$remote_addr - $remote_user [$time_local] "$request_method $filtered_request_uri $server_protocol" $status $body_bytes_sent "$filtered_http_referer" "$http_user_agent"';
server_names_hash_bucket_size 64;
# sendfile on;
tcp_nopush on;
tcp_nodelay on;
# keepalive_timeout 65;
gzip on;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_proxied any;
gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/json;
# include /opt/gitlab/embedded/conf/mime.types;
proxy_cache_path proxy_cache keys_zone=gitlab:10m max_size=1g levels=1:2;
proxy_cache gitlab;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# Remove private_token from the request URI
# In: /foo?private_token=unfiltered&authenticity_token=unfiltered&rss_token=unfiltered&...
# Out: /foo?private_token=[FILTERED]&authenticity_token=unfiltered&rss_token=unfiltered&...
map $request_uri $temp_request_uri_1 {
default $request_uri;
~(?i)^(?<start>.*)(?<temp>[\?&]private[\-_]token)=[^&]*(?<rest>.*)$ "$start$temp=[FILTERED]$rest";
}
# Remove authenticity_token from the request URI
# In: /foo?private_token=[FILTERED]&authenticity_token=unfiltered&rss_token=unfiltered&...
# Out: /foo?private_token=[FILTERED]&authenticity_token=[FILTERED]&rss_token=unfiltered&...
map $temp_request_uri_1 $temp_request_uri_2 {
default $temp_request_uri_1;
~(?i)^(?<start>.*)(?<temp>[\?&]authenticity[\-_]token)=[^&]*(?<rest>.*)$ "$start$temp=[FILTERED]$rest";
}
# Remove rss_token from the request URI
# In: /foo?private_token=[FILTERED]&authenticity_token=[FILTERED]&rss_token=unfiltered&...
# Out: /foo?private_token=[FILTERED]&authenticity_token=[FILTERED]&rss_token=[FILTERED]&...
map $temp_request_uri_2 $filtered_request_uri {
default $temp_request_uri_2;
~(?i)^(?<start>.*)(?<temp>[\?&]rss[\-_]token)=[^&]*(?<rest>.*)$ "$start$temp=[FILTERED]$rest";
}
# A version of the referer without the query string
map $http_referer $filtered_http_referer {
default $http_referer;
~^(?<temp>.*)\? $temp;
}
server {
listen 8091;
server_name localhost;
location / {
root html;
index index.html index.htm;
proxy_pass http://127.0.0.1:8891;
}
}
include /var/opt/gitlab/nginx/conf/gitlab-http.conf;
include /var/opt/gitlab/nginx/conf/nginx-status.conf;
一切顺利的话,现在就可以kill掉gitlab内嵌的nginx,并且启动自己私有的nginx了
[root@AliS ~]# /usr/local/nginx/sbin/nginx
如果幸运的话,你可以快乐的用ps -ef|grep nginx看到你的nginx在快乐的奔跑,但是显然,我不太幸运。我运行的时候,系统残酷的提示我
nginx: error while loading shared libraries: xxxx.so
这个时候,可以使用一个叫做ldd的命令去看,导致都有哪些库没找到。如果没找到,会在对应的库文件下写not found。这个时候,去看看gitlab内嵌的nginx的库文件在哪,做个软链接到/lib64下就好了。
下面给大家看看ldd的输出,我的因为写文章之前已经做过软链接了,所以就看不到报错了
[root@AliS ~]# ldd /usr/local/nginx/sbin/nginx
linux-vdso.so.1 => (0x00007ffc3bbd6000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f6fc1446000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f6fc122a000)
libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f6fc0ff2000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f6fc0d90000)
libssl.so.1.0.0 => /lib64/libssl.so.1.0.0 (0x00007f6fc0b1e000)
libcrypto.so.1.0.0 => /lib64/libcrypto.so.1.0.0 (0x00007f6fc06d0000)
libz.so.1 => /lib64/libz.so.1 (0x00007f6fc04ba000)
libxml2.so.2 => /lib64/libxml2.so.2 (0x00007f6fc0150000)
libxslt.so.1 => /lib64/libxslt.so.1 (0x00007f6fbff10000)
libexslt.so.0 => /lib64/libexslt.so.0 (0x00007f6fbfcfb000)
libc.so.6 => /lib64/libc.so.6 (0x00007f6fbf938000)
/lib64/ld-linux-x86-64.so.2 (0x000055ad92e0a000)
libfreebl3.so => /lib64/libfreebl3.so (0x00007f6fbf734000)
liblzma.so.5 => /lib64/liblzma.so.5 (0x00007f6fbf50e000)
libm.so.6 => /lib64/libm.so.6 (0x00007f6fbf20c000)
libgcrypt.so.11 => /lib64/libgcrypt.so.11 (0x00007f6fbef8a000)
libgpg-error.so.0 => /lib64/libgpg-error.so.0 (0x00007f6fbed85000)
[root@AliS ~]#
之后就是让gitlab配置生效了
[root@AliS ~]# gitlab-ctl reconfigure
[root@AliS ~]# gitlab-ctl restart
gitlab提供了一个简单的命令把相关的log打印在一起,如果里面没有报错就没啥问题了。
[root@AliS ~]# gitlab-ctl tail
最后就是测试一下,打开一个浏览器输入gitlab的地址,看看能不能正常访问了(虽然只是简单的一句话,但是为了实现这句话花费了我一包烟的时间)
配置webdav功能
端口 | 端口定义 |
---|---|
8094 | 私有nginx提供的webdav对外访问端口 |
那些没在系统上部署过gitlab的烟民可以回来了
私有nginx运行正常后,配置webdav的过程就比较简单了
给webdav建个带目录不能直接登录的组和用户,然后再在webdav的home目录建立个用来存放数据的目录,我的是/home/webdav/data
下面这堆命令都是新建用户的固定搭配
[root@AliS home]# groupadd webdav
[root@AliS home]# useradd -d /home/webdav -g webdav -s /sbin/nologin webdav
[root@AliS home]# cd webdav
[root@AliS webdav]# mkdir data
[root@AliS webdav]# ls
data
[root@AliS webdav]# pwd
/home/webdav
[root@AliS webdav]# chown webdav:webdav data
[root@AliS webdav]# ls -l
total 4
drwxr-xr-x 2 webdav webdav 4096 Jul 11 21:30 data
之后回到私有nginx的conf目录,给webdav建立一个用户存放用户名密码的shadow文件
echo 用户名:$(openssl passwd -crypt 密码)>/etc/nginx/webdavpasswd
[root@AliS nginx]# mkdir webdav
[root@AliS nginx]# echo omniuser:$(openssl passwd -crypt omnipassword)>/usr/local/nginx/webdav/webdavpasswd
在/usr/local/nginx/conf/vhosts下添加一个vhosts的配置文件,我的是webdav.conf
文件内容如下
server {
server_name localhost;
listen 8094;
location / {
set $dest $http_destination;
if (-d $request_filename) {
rewrite ^(.*[^/])$ $1/;
set $dest $dest/;
}
if ($request_method ~ MKCOL) {
rewrite ^(.*[^/])$ $1/ break;
}
root /home/webdav/data;
autoindex on;
dav_methods PUT DELETE MKCOL COPY MOVE;
dav_ext_methods PROPFIND OPTIONS;
create_full_put_path on;
client_max_body_size 0M;
dav_access user:rw group:rw all:rw;
auth_basic "Authorized Users Only";
auth_basic_user_file /usr/local/nginx/webdav/webdavpasswd;
}
}
- 文件里定义的8094是自选的webdav服务端口
- root /home/webdav/data;这句的路径是你自己建立的webdav存放数据的目录
- auth_basic_user_file /usr/local/nginx/webdav/webdavpasswd;这个路径是刚刚你再nginx里面建立的用于存放webdav登录的用户名密码文件地址
最后让nginx重新加载下配置文件,基本配置就完成了
[root@AliS webdav]# /usr/local/nginx/sbin/nginx -s reload
后面测试一下,我的linux是没有装davfs的,所以要想在本机测试,要先让系统支持davfs的mount
[root@AliS mnt]# yum search davfs
Failed to set locale, defaulting to C
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
===================================================================== N/S matched: davfs =====================================================================
davfs2.x86_64 : A filesystem driver for WebDAV
Name and summary matches only, use "search all" for everything.
[root@AliS mnt]#
[root@AliS mnt]# yum install -y davfs2.x86_64
Failed to set locale, defaulting to C
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Resolving Dependencies
--> Running transaction check
---> Package davfs2.x86_64 0:1.4.7-6.el7 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
==============================================================================================================================================================
Package Arch Version Repository Size
==============================================================================================================================================================
Installing:
davfs2 x86_64 1.4.7-6.el7 epel 148 k
Transaction Summary
==============================================================================================================================================================
Install 1 Package
Total download size: 148 k
Installed size: 341 k
Downloading packages:
davfs2-1.4.7-6.el7.x86_64.rpm | 148 kB 00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : davfs2-1.4.7-6.el7.x86_64 1/1
Verifying : davfs2-1.4.7-6.el7.x86_64 1/1
Installed:
davfs2.x86_64 0:1.4.7-6.el7
Complete!
装好啦,改改配置,我也把use_locks改成了0
[root@AliS mnt]# vi /etc/davfs2/davfs2.conf
mount一下试试,能挂载上就是做好了
[root@AliS mnt]# mkdir webdav
[root@AliS mnt]# mount -t davfs http://50.50.50.50:8094 /mnt/webdav
Please enter the username to authenticate with server
http://50.50.50.50:8094 or hit enter for none.
Username: omni
Please enter the password to authenticate user webdav with server
http://50.50.50.50:8094 or hit enter for none.
Password:
/sbin/mount.davfs: Warning: can't write entry into mtab, but will mount the file system anyway
[root@AliS mnt]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 29G 8.5G 78% /
devtmpfs 7.8G 0 7.8G 0% /dev
tmpfs 7.8G 4.0K 7.8G 1% /dev/shm
tmpfs 7.8G 480K 7.8G 1% /run
tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup
tmpfs 1.6G 0 1.6G 0% /run/user/0
http://50.50.50.50:8094 26G 13G 13G 50% /mnt/webdav
[root@AliS mnt]# ls
webdav
[root@AliS mnt]# cd webdav/
[root@AliS webdav]# ls
lost+found
当然,上面我删除了一部分信息。我自然没有文章中写的这么顺利,现实和理论总是有差距的,我一直都是下列错误
[root@AliS mnt]# mount -t davfs http://http://50.50.50.50:8094 /mnt/webdav
mount: unknown filesystem type 'davfs'
- 没装davfs的文件系统支持,装就好了
[root@AliS mnt]# mount -t davfs http://http://50.50.50.50:8094 /mnt/webdav
/sbin/mount.davfs: invalid URL
- 打错了url路径,都是小事儿
[root@AliS mnt]# mount -t davfs http://50.50.50.50:8094 /mnt/webdav
Please enter the username to authenticate with server
http://50.50.50.50:8094 or hit enter for none.
Username: webdav
Please enter the password to authenticate user webdav with server
http://50.50.50.50:8094 or hit enter for none.
Password:
/sbin/mount.davfs: connection timed out two times;
- 这个问题晕了我好久,直到我上阳台抽烟冷静了两次,才想起来,阿里云对外访问端口还需要去它的安全控制台独立配置一下入栈出栈规则,不然默认的安全策略端口是不被外部访问的
omnifocus配置
一切准备妥当,软件这边的设置就异常简单了
只要在omnifocus的设置/同步功能里面,把对应的webdav的服务器地址(http://50.50.50.50:8094)连带端口号填好,输入用户名密码就好了。唯一需要注意的是,用于同步的第一个设备的数据,将成为服务器上的原始数据库,之后这个数据会覆盖其他后加入同步的设备。小心不要用错误数据覆盖正确数据就好了。
参考文章
最后多谢写这些文章的大神们
- 利用Nginx WebDAV搭建自己的网盘
- 替换gitlab自带的Nginx,并修改仓库存储路径
- nginx配置虚拟主机vhost的方法详解
- Markdown基本语法
- 原谅我不好用的脑袋,写个文章还得时不时的查下Markdown的语法……