查看原文
其他

在Ubuntu服务器上配置Shiny应用

豆豆花花 生信星球 2023-09-18
 今天是生信星球陪你的第874天

   大神一句话,菜鸟跑半年。我不是大神,但我可以缩短你走弯路的半年~

   就像歌儿唱的那样,如果你不知道该往哪儿走,就留在这学点生信好不好~

   这里有豆豆和花花的学习历程,从新手到进阶,生信路上有你有我!

豆豆写于2022.6.28
附上一个实用的英文链接:
https://www.charlesbordet.com/en/guide-shiny-aws/#4-deploy-the-app-on-the-serve

0 前言

之前看到腾讯云在搞618活动,推出了轻量服务器,价格比较合适,300多元就能使用10M带宽,这应该对网页服务器比较有帮助

优惠活动在:https://cloud.tencent.com/act/pro/computeinit618

它和云服务器有一些区别,不过对于我们非专业领域人士,应该也是性价比较高了:

除此以外,还有学生优惠:

  • 阿里学生:https://developer.aliyun.com/plan/grow-up

  • 腾讯学生:https://cloud.tencent.com/act/campus

1 开箱

推荐配置ubuntu,后面比较好操作,centos要麻烦一点

1.1 首先配置登陆用户名和密码

首次登陆修改只能使用默认的用户名ubuntu,设置好以后会强制关机重启【因为我选择了ubuntu系统,所以这个用户名默认是这个,其他系统会有所不同】

1.2 然后登陆

ssh ubuntu@你的公网ip

查看系统配置

lsb_release -a #然后得到详细系统版本

No LSB modules are available.
Distributor ID:    Ubuntu
Description:    Ubuntu 18.04.4 LTS
Release:    18.04
Codename:    bionic

1.3 新建用户

sudo -i adduser reed
# 然后输入用户名密码
# 其余选择一律enter跳过

1.4 提高新用户权限

# 在初始账号(ubuntu)下
sudo -i
# 然后
vi  /etc/sudoers
# 在最后一行添加
reed ALL=(ALL:ALL) NOPASSWD: ALL
# 最后:x!强制保存退出
# 之后reed账户可以使用sudo -i直接切换成root了

如果你不想每次ssh登录都输入密码,可以参考:小服务器,快记住我的密码吧

2 安装&配置

2.1 安装依赖库

sudo apt install --fix-missing libcurl4-openssl-dev libxml2-dev libgdal-dev libssl-dev libglu1-mesa-dev libmagick++-dev libudunits2-dev 

2.2 安装R

参考:https://cloud.r-project.org/bin/linux/ubuntu/

sudo vim /etc/apt/sources.list
# 然后将下面👇这样加到最后
deb http://mirrors.tuna.tsinghua.edu.cn/CRAN/bin/linux/ubuntu xenial/

#
 添加公匙
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9

sudo add-apt-repository 'deb https://cloud.r-project.org/bin/linux/ubuntu bionic-cran40/'
sudo apt update
sudo apt install r-base
# 目前安装的是:R version 4.2.0 (2022-04-22)

2.3 安装Shiny server

参考:https://www.rstudio.com/products/shiny/download-server/ubuntu/

sudo su - \
-c "R -e \"install.packages('shiny', repos='https://mirrors.tuna.tsinghua.edu.cn/CRAN/')\""

sudo apt-get install gdebi-core
wget https://download3.rstudio.org/ubuntu-18.04/x86_64/shiny-server-1.5.18.987-amd64.deb
sudo gdebi shiny-server-1.5.18.987-amd64.deb

安装好以后,会自动新建一个shiny的用户

需要对shiny用户做一些简单的设置

# 先切换到root模式
sudo -i 
# 然后设定密码
sudo passwd shiny # 同样可以参考之前的1.4部分,提高它的权限

# 添加组
sudo groupadd shiny-apps
sudo usermod -aG shiny-apps shiny
sudo usermod -aG shiny-apps reed # 也允许主用户可以访问

# change owner:将指定文件的拥有者改为指定的用户或组
sudo chown -R shiny:shiny-apps /srv/shiny-server
sudo chmod g+w /srv/shiny-server
sudo chmod g+s /srv/shiny-server
# g - the permissions that other users in the file's group have for it
# w - set user or group ID have right to write
# s - set user or group ID have right to execute

# 设置完成,查看【/srv/shiny-server这个目录就是存放各种shiny app的地方啦】
ls -l /srv/shiny-server
# total 0
# lrwxrwxrwx 1 shiny shiny-apps 38 Jun 28 13:17 index.html -> /opt/shiny-server/samples/welcome.html
# lrwxrwxrwx 1 shiny shiny-apps 37 Jun 28 13:17 sample-apps -> /opt/shiny-server/samples/sample-apps

# 之后我们都用shiny这个用户安装R包
su - shiny

2.3 安装Rstudio server

https://www.rstudio.com/products/rstudio/download-server/debian-ubuntu/

wget https://download2.rstudio.org/server/bionic/amd64/rstudio-server-2022.02.3-492-amd64.deb
sudo gdebi rstudio-server-2022.02.3-492-amd64.deb

2.4 安装R包

首先切换到shiny用户,然后再操作!

配置.Rprofile

# 命令
vi .Rprofile
# 然后输入下面👇
Sys.setenv(LANG="en_US.UTF-8")
options=(repo = c(CRAN = "https://mirrors.tuna.tsinghua.edu.cn/CRAN/"))
options(BioC_mirror="https://mirrors.tuna.tsinghua.edu.cn/bioconductor")
# 最后保存退出

配置.Renviron

提示:如果你写下面的这个路径,前提你得有这个目录,因此需要先新建目录

mkdir /home/shiny/R_Library

#
 命令
vi .Renviron
# 然后输入下面👇
R_LIBS=/home/shiny/R_Library
# 最后保存退出

因为我们是要配置shiny网页,所以接下来我们需要以shiny 用户登陆

# 之后我们都用shiny这个用户安装R包
su - shiny

####################
# 下面👇均在R中进行  #
####################

# 配置镜像 (前面配置过.Rprofile的话,可以跳过)
local({
  r <- getOption( "repos" ); 
  r[ "CRAN" ] <- "https://mirrors.tuna.tsinghua.edu.cn/CRAN/"
  options( repos = r )
  BioC <- getOption( "BioC_mirror" ); 
  BioC[ "BioC_mirror" ] <- "https://mirrors.ustc.edu.cn/bioc/"
  options( BioC_mirror = BioC )
})
# 需要安装的R包 (我分别安装shiny需要的包和另外需要依赖的包)
shiny_pkgs <- c("colourpicker""rvg""tikzDevice""openxlsx""futile.logger""ggplot2""igraph""ggraph""shiny""shinyBS""shinyAce""shinyWidgets""shinydashboard""stringr""DT""R.utils""knitr""rmarkdown""shinyjs""cowplot""RColorBrewer""waiter""VennDiagram""extrafont""ggupset")

other_pkgs <- c("clusterProfiler""dplyr""DOSE""europepmc""fst""ggplot2""ggraph""igraph""magrittr""openxlsx""stringr""stringi""tidyr""VennDiagram""rlang""AnnotationDbi""BiocManager""cowplot""ComplexUpset""data.table""forcats""fgsea""futile.logger""ggplotify""ggsci""ggupset""ggrepel""ggridges""ggnewscale""GOplot""GOSemSim""labeling""msigdbr""pheatmap""tm""treemap""RColorBrewer""rappdirs""RCurl""reshape2""rio""rrvgo""scales""stats""testthat""tibble""wordcloud""knitr""rmarkdown","markdown","pacman")

orgdb_pkgs <- c("org.Hs.eg.db","org.Mm.eg.db","org.Rn.eg.db","org.Dm.eg.db",
                "org.At.tair.db","org.Sc.sgd.db","org.Dr.eg.db","org.Ce.eg.db","org.Bt.eg.db",
               "org.Ss.eg.db","org.Gg.eg.db","org.Mmu.eg.db","org.Cf.eg.db","org.EcK12.eg.db",
               "org.Xl.eg.db","org.Ag.eg.db","org.Pt.eg.db","org.EcSakai.eg.db","org.Mxanthus.db")

probe_pkgs  <- c("hcg110.db""hgfocus.db""hgu133a.db""hgu133a2.db"
"hgu133b.db""hgu133plus2.db""hgu95a.db""hgu95av2.db""hgu95b.db"
"hgu95c.db""hgu95d.db""hgu95e.db""hta20probeset.db""hthgu133pluspm.db"
"hugene10sttranscriptcluster.db""hugene20sttranscriptcluster.db"
"hugene21sttranscriptcluster.db""u133x3p.db""illuminaHumanv3.db"
"illuminaHumanv4.db""illuminaHumanv1.db""illuminaHumanv2.db"
)

all_pkgs <- c(shiny_pkgs,other_pkgs,orgdb_pkgs,probe_pkgs)

# 判断式安装
if (!requireNamespace("BiocManager", quietly = TRUE)){
      install.packages("BiocManager")
}
CRANpackages <- available.packages() # 全部的CRAN包
lapply( all_pkgs, 
  function( p ){
    if( !require( p, character.only = T ) ){
      if( p %in% rownames( CRANpackages) ){
        install.packages( p )
      }else{
        BiocManager::install( p, suppressUpdates = FALSE, ask = FALSE)
      }
    }
  }
)

3 启动

3.1 添加端口,实现Shiny和Rstudio自由

虽然我们服务器已经安装成功并且激活了这两个功能,但是要从网页去访问,还得设置好服务器端口

防火墙中进行设置:shiny默认设置3838端口,rstudio默认是8787 端口(这个默认端口后续可以修改,防止别人拿到你的IP就去8787…)

3.2 让shiny项目成真

首先把项目放在自己的家目录

# 方案1:项目在github上,可以直接git clone
cd /home/shiny
git clone 你的项目地址

#
 方案2:本地上传
scp -r /本地目录/app shiny@你的IP地址:/home/shiny
# 然后在服务器上设置这个目录的可读权限
chmod 400 /home/shiny/app

然后在/srv/shiny-server 中加入项目的快捷方式

sudo ln -s /home/shiny/app /srv/shiny-server
# 同时更改项目属主是shiny
sudo chown -R shiny app/

然后重启

sudo systemctl restart shiny-server.service

之后输入:http://你的IP:3838/你的shiny项目名称

如果放置了多个应用,那么就需要:

  • http://你的IP:3838/应用1

  • http://你的IP:3838/应用2

可能的报错

如果无法运行shiny app,去/var/log/shiny-server/目录下看看log文件中的报错信息,一般是由于缺少包

解决后,立刻就能恢复运行

4 Nginx反向代理

它的用处就是:帮我们自动去掉那个烦人的3838 ,省得每次都输入

反向代理,用比较现实点的例子解释:

  • 外卖小哥想给3838这个房间送物资

  • 由于疫情防控,不让进去,只能交给门口的居委会工作人员

  • 居委会人员帮外卖小哥把物资送到3838房间

服务器也是如此:

  • 用户给3838端口发个指令,想获取其中的内容

  • 服务器中的Nginx现在实行统一管理,它负责调度

  • Nginx帮用户把指令送去3838

Nginx这个过程实现,利用的就是服务器中默认的HTTP网站端口:80

4.1 安装Nginx

sudo apt-get update
sudo apt-get install nginx
sudo systemctl start nginx

4.2 配置Nginx

cd /etc/nginx/sites-available
sudo vi shiny.conf

#
 添加以下👇信息,然后保存退出
server {
    # listen 80 means the Nginx server listens on the 80 port.
    listen 80;
    listen [::]:80;
    # Replace it with your (sub)domain name.
    server_name 域名1 域名2(如果你只有一个域名,就只写一个);
    # The reverse proxy, keep this unchanged:
    location / {
        proxy_pass http://localhost:3838;
        proxy_redirect http://localhost:3838/ $scheme://$host/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_read_timeout 20d;
        proxy_buffering off;
    }
}

#
 然后设置软连接
cd ../sites-enabled
sudo ln -s ../sites-available/shiny.conf .

#
 然后切换root用户
sudo -i 

#
 修改/etc/nginx/nginx.conf
vi /etc/nginx/nginx.conf
# 在其中的http区域中添加下面👇信息
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;

4.3 最后激活

sudo nginx -t
# 成功会提示:
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful
sudo systemctl restart nginx

5 优化

5.1 删掉原来的shiny app

默认情况下,直接输入IP地址会显示自带的shiny app模板:

只要测试shiny可以用了,就可以删掉它了:

sudo rm -rf /srv/shiny-server/sample-apps

5.2 如果只有一个shiny app

然后如果目前只有一个shiny app,不希望用www.main.com/myapp 这样的方式,而是直接一点:www.myapp.com

可以修改shiny-server的配置文件

sudo vi /etc/shiny-server/shiny-server.conf
# 下面👇是全部内容

#
 Instruct Shiny Server to run applications as the user "shiny"
run_as shiny;
preserve_logs true; # 保存报错日志(shiny默认犯了错秒删。。。)
sanitize_errors false;

#
 Define a server that listens on port 3838
server {
  listen 3838;

  #
 Define a location at the base URL
  location / {

    # 默认存放shiny app的目录
    site_dir /srv/shiny-server;

    # 默认存放shiny 日志文件的目录
    log_dir /var/log/shiny-server;

    # 我们之前将index.html删掉了,我们又不希望别人看到我们shiny app的布局,可以隐藏首页,直接进入shiny
    directory_index off;
  }

  #
# 我们每个单独的应用可以设置自己的存放目录(这里设置主页就显示app)
  location / {
    app_dir /home/shiny/app; #location to the app
    log_dir /var/log/shiny-server/app; # log
    }

   ## 如果还有其他app
   location / {
    app_dir /home/shiny/app2; #location to the app
    log_dir /var/log/shiny-server/app2; # log
    }

}

#
 最后保存退出

#
 然后将/srv/shiny-server 属主切换回shiny
sudo chown -R shiny:shiny-apps /srv/shiny-server

重启:sudo systemctl restart shiny-server.service

到此为止,你应该可以直接输入IP地址来访问到你的应用
下面👇,我们继续优化这个网址

5.3 给IP起个简单的名字吧 =》 解析域名

为了方便宣传,我们一般不会直接给别人一串数字的IP地址,而且给它起个名字,这就是设置域名

有一家比较知名的域名公司:https://www.godaddy.com/zh-sg

他们还可以提供域名经纪服务、域名价值评估

选好心仪的域名后,一般等待1-2天实名认证,通过了就可以设置DNS record

首页DNS =》 管理区域 =》DNS记录

然后修改类型A的数据为你的IP地址

最后,重新进入【4.2 配置Nginx】 ,将server_name修改为你的域名(而不是IP),再进行【4.3 最后激活】

5.4 【可选】备案

如果域名解析到的服务器在中国香港、中国台湾、中国澳门、或非中国的国家和地区,则不需要备案

每个国内的云平台都有自己的备案方式,都是相当麻烦,这里以腾讯云为例:

需要实名上传身份证+视频核验,填写网站用途+中文描述,需要承诺书请手写正楷签字(接受签名章,请勿使用连笔签)=》然后当地网管打电话审核=》国家网管局审核 =》 审核通过,必须在主页下方放上备案号

5.5 给域名加个锁

”锁“就是HTTPS

HTTPS就是防止在HTTP的传输过程中,因信息未加密而被别有用心的人拦截篡改

HTTPS和HTTP的区别有:

  • https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

  • http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。

  • http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443

首先利用Let’s Encrypt获取免费证书

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot python-certbot-nginx 
# 获取证书
sudo certbot certonly --nginx -d 自己的域名
# 需要注意:这个域名必须已经被解析

然后这个证书就被放在:/etc/letsencrypt/live/你的域名/ 这个目录中

然后安装证书

HTTP默认监听80端口,HTTPS则是443端口,这里我们将Nginx增加监听443

curl https://ssl-config.mozilla.org/ffdhe2048.txt > /home/shiny/dhparam.pem

sudo vi /etc/nginx/sites-available/shiny.conf

#
 最终版本(注意将”你的域名“这里替换掉)
server {
    listen 80;
    listen [::]:80;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name 这里放自己的域名;
    # The reverse proxy, keep this unchanged:
    location / {
        proxy_pass http://localhost:3838;
        proxy_redirect http://localhost:3838/ $scheme://$host/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_read_timeout 20d;
        proxy_buffering off;
    }


#
 certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
ssl_certificate /etc/letsencrypt/live/你的域名/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/你的域名/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
ssl_session_tickets off;

#
 curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam.pem
ssl_dhparam /home/shiny/dhparam.pem;

#
 intermediate configuration
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;

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

#
 OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;

#
 verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /etc/letsencrypt/live/你的域名/chain.pem;
}

接着检查

 sudo nginx -t
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

最后重启

sudo systemctl restart nginx
sudo systemctl restart shiny-server.service

添加自动更新

Certbot会自动检测证书是否过期,并且提前更新新的证书

sudo certbot renew --dry-run

感想

期间换了几个服务器折腾了几次,包括:腾讯云(广州节点)、AWS(美国节点)、阿里云(主要使用它的香港节点),以及不知名的一些香港云服务器,感觉还是得大品牌的靠谱,虽然价格高一点,但用着省心;然后就是要考虑你的需求,如果是想兼顾海外和国内用户,最好是香港的服务器,还不用备案,当然它的价格要比内地IP贵一点。另外经过这一次使用DoDaddy服务,感觉还不错,它自己的DNS配置很快并且比较稳定。

最后,还是那句~生信在于折腾!

zzz 补充

z1: 卸载R

sudo apt-get autoremove r-base-core

z2: 服务器总是自动断线

sudo vim /etc/ssh/sshd_config
# 找到下面这两行
#ClientAliveInterval 0
#ClientAliveCountMax 3

#
 然后去掉注释,并且修改
ClientAliveInterval 30 #意思是:服务端每隔多少秒向客户端发送一个信号
ClientAliveCountMax 86400 #意思是:客户端多少次没有相应,服务器自动断掉连接

#
 最后重启ssh
service sshd restart

z3: 如果安装出现依赖项缺失,则在命令行安装缺失项

sudo apt-get -y install libcurl4-gnutls-dev  libxml2-dev libssl-dev subversion scons libfuse-dev gcc
sudo apt-get -y install  libmariadb-client-lgpl-dev libcurl4-openssl-dev libudunits2-dev

z4: 设置了端口,Rstudio server还是登录不上

可能是防火墙拦截了

# 首先安装
sudo apt-get update 
sudo apt-get install iptables
sudo apt-get install iptables-persistent

#
 然后运行
# 开放端口
iptables -I INPUT -p tcp --dport 8787 -j ACCEPT
iptables -I OUTPUT -p udp --dport 8787 -j ACCEPT
# 保存防火墙规则, /etc/iptables/rules.v4
sudo netfilter-persistent save

z5: 关于Rstudio-server 配置文件

主要有两个:

  • /etc/rstudio/rserver.conf

  • /etc/rstudio/rsession.conf

其中:

###############################
# 关于 rserver.conf 常用的配置
###############################
# 监听端口,默认为 8787
www-port=8787
# 地址,默认为0.0.0.0,会接收任何IP连接
www-address=0.0.0.0
# 指定库文件路径,一般不需要改动,可以用于添加系统标准库,第三方外部库文件依赖
rsession-ld-library-path=/opt/local/lib:/opt/local/someapp/lib
# 指定 R 路径
rsession-which-r=/usr/local/bin/R
# 设置用户组(方便增加多用户)
auth-required-user-group=rstudio-group

#
##############################
# 关于 rsession.conf 常用的配置
###############################
# 会话超时,默认 2 小时 Rstudio 没有操作就会断开服务器连接,如果有任务运行不会断开
session-timeout-minutes=120
# 设置R包路径,默认在~/R/packages
r-libs-user=~/R/packages
# 镜像设置
r-cran-repos=https://mirrors.tuna.tsinghua.edu.cn/CRAN/

z6: Rstudio server常用操作

  • 启动:sudo rstudio-server start

  • 关闭:sudo rstudio-server stop

  • 重启:sudo rstudio-server restart

  • 查看状态:sudo rstudio-server status

z7: Shiny server 常用操作

  • 启动:
    sudo systemctl start shiny-server
    sudo systemctl enable shiny-server

  • 重启: sudo systemctl restart shiny-server.service

  • 查看日志:cat /var/log/shiny-server.log

z8: 如果发现新建的用户使用tab补全失效

对于共用一台服务器的用户来说,一个新用户可能并没有对bashrc文件进行初始化,只需要一个命令解决:env -i bash

z9: 不同服务器之间快速拷贝数据

rsync -av 用户名1@第一台服务器IP:/home/data 用户名1@第二台服务器IP:/home

z10: Rstudio server添加新用户

之前我们在z5中设置了Rstudio-server 配置文件,其中指定了auth-required-user-group=rstudio-group

这里只需要将新用户放进这个组中即可

sudo groupadd rstudio-group 
sudo usermod -a -G rstudio-group shiny
# 查看一下
id shiny
# uid=999(shiny) gid=999(shiny) groups=999(shiny),1002(shiny-apps),1003(rstudio-group)

z11:安装某个R包报错提示:ERROR: no packages specified

可能当前你的用户不是shiny用户,切换回去就好啦

z12: 如果你发现配置文件写的都是对的,但是网页不显示或者显示的不是shiny app

查看配置文件的属主和属组是不是shiny,因为有时可能切换到root直接去运行命令,导致配置文件的归属直接改成了root,默认的shiny用户无法访问到这些配置文件

如果是这种情况,直接切换回来就好

# 比如不小心使用了root操作,改变了它的所属
ls -lh ../sites-available/shiny.conf
# -rw-r--r-- 1 root root 1.7K Jun 30 21:23 ../sites-available/shiny.conf

#
 更改回来即可(如果是更改整个目录,就加 -R )
sudo chown shiny:shiny-apps ../sites-available/shiny.conf
ls -lh ../sites-available/shiny.conf
# -rw-r--r-- 1 shiny shiny-apps 1.7K Jun 30 21:23 ../sites-available/shiny.conf

点击底部的“阅读原文”,获得更好的阅读体验哦😻

初学生信,很荣幸带你迈出第一步

🤓 生信星球 🌎 一个不拽术语、通俗易懂的生信知识平台

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存