分类目录归档:IT

部分 Seedbox 使用的 systemd 自动启动脚本

本文仅供记录使用,可能将合并入将来撰写的系列文章:”大刷子的养成方法“

所有脚本存放于 /etc/systemd/system 目录下

Deluge 及其 WebUI 的 SystemD 启动脚本:

[Unit]
Description=Deluged
After=network-online.target

[Service]
ExecStart=/usr/bin/deluged -d
ExecStop=/bin/kill -9 $(/bin/cat /run/deluged.pid)
Restart=always
PIDFile=/run/deluged.pid
TimeoutStopSec=300

[Install]
WantedBy=multi-user.target
[Unit]
Description=Deluge-web
After=network-online.target deluged.service
Wants=deluged.service

[Service]
ExecStart=/usr/bin/deluge-web
ExecStop=/bin/kill -9 $(/bin/cat /run/deluge-web.pid)
Restart=always
PIDFile=/run/deluge-web.pid

[Install]
WantedBy=multi-user.target

VNCserver 启动脚本:

[Unit]
Description=VNCserver
After=syslog.target network.target

[Service]
ExecStart=/usr/bin/sudo /usr/bin/vncserver :1
ExecStop=/usr/bin/sudo /usr/bin/vncserver -kill :1
ExecStartPre=-/usr/bin/sudo /usr/bin/vncserver -kill :1 > /dev/null 2>&1
Restart=always
Type=forking
#PIDFile=/run/vncserver.pid

[Install]
WantedBy=multi-user.target

OpenVZ 下 TunnelBroker 实现(借助 tb_tun 实现):

[Unit]
Description=ipv6tb
After=network-online.target

[Service]
Type=forking
ExecStart=/usr/bin/sudo /etc/init.d/ipv6tb start
ExecStop=/usr/bin/sudo /etc/init.d/ipv6tb stop
Restart=always

[Install]
WantedBy=multi-user.target

执行 systemctl enable <serviceName> 安装服务

写入完成之后,执行 systemctl daemon-reload 载入 service 文件,再使用 systemctl start <serviceName> 运行服务,或者重启测试

一些说明:

  • Type=forking 代表该启动脚本需要 systemd 跟踪 fork 出来的进程,在执行脚本的时候可能需要,以及 vncserver 这样需要启动桌面环境(其他进程)的启动项
  • VNCserver 采用 sudo 运行的原因是需要指定运行环境变量,如果直接运行 /usr/bin/vncserver 会有 vncserver: The HOME environment variable is not set. 的错误,为了方便直接指定 sudo 采用 root 环境运行
  • Systemd 脚本需要写绝对路径,不能写相对路径

Amazon AWS 配置 TensorFlow 与 Keras 环境记录

因为一些需求,需要在 AWS 上进行一些 GPU 的计算,按道理 AWS 已经提供了深度学习的 AMI 映像供我们使用,但是我实在是搞不清他到底做了些什么,因此也不怎么会用。加上自带各种用不到的库实在太大,为了放下我所有的数据需要开 80G 的 EBS 存储卷,感觉有些小贵,无奈之下只能从最干净的 Ubuntu 16.04 开始配置一台符合我需求的 EC2 实例。

具体步骤我打算按照 Keras 官方文档上的方案,由于我也不确定能不能搞定,这里就做一个实时的记录:

  • 配置 python 与 CUDA 环境,这个相对比较简单,需要注意一点的是 cuDNN 库需要在国内自己找,这个 CSDN 上有很多,文件名是 cudnn-8.0-linux-x64-v5.1.tgz 就好了。这一步我进行得十分顺利。
  • Keras 相关依赖包的安装,这里开始出现了问题
    • 首先安装 Anaconda,需要注意一点的是,Anaconda 安装包会将其自身路径写入 .bashrc,但是需要执行 source .bashrc 这条命令才能使 Anaconda 做的修改生效,这里一定要注意,不要认为是安装出了问题。完成之后运行 python,应该就会发现你的 python 已经是 Anaconda 发行版了。
    • 接下来 pip install –U –pre pip setuptools wheel 这步也出现了问题,执行 pip 后报错 “FileNotFoundError: [Errno 2] No such file or directory: ‘/home/ubuntu/anaconda3/lib/python3.6/site-packages/setuptools-27.2.0-py3.6.egg’
      • 解决方案是这里,手工指定 setuptools 版本进行安装:pip install setuptools==27.2.0
    • 然后是安装 scipy numpy tensorflow-gpu keras 等一干所必要的包,安装一切顺利
    • 检查 TensorFlow 安装时再次出现问题,import tensorflow 出现 ImportError: libcudnn.so.6: cannot open shared object file: No such file or directory
      • 查询后发现,pip 默认安装是 tensorflow 1.3,这个版本需要 cuDNN 6.0,但是考虑到教程通用性需求,不选择升级到 tf 1.3,采用 pip install –U –pre tensorflow-gpu==1.2 命令强制安装 1.2 版本使用 cuDNN 5.1

之后的操作就相当顺利了,所有的操作都和本地类似,还是熟悉的东西好用啊。

由于我不需要现在就继续进行计算,因此在停止了实例之后,为其配置的环境创建一个 AMI,供下次继续计算时开启竞价型实例使用。

网站备份与 Jailed SSH User 的实现

之前在看一些 VPS 博客的时候经常看到这样的一句话:“任何服务商都不会永久稳定,要做好数据备份”,虽然我本人还没遇到跑路的 VPS 服务提供商,Scaleway 的东家 Online 也是存在了快十年的公司了,但这也不意味着备份就是不必要的,毕竟这不是 PT 盒子,关停了再配置一个也就是最多半天的事情,如果自己写了几年的文章,突然就因为什么不可抗力的原因全都没了,这种打击估计谁也受不了,因此在我在这个博客架设之初就必须考虑到备份的问题。

备份一般来说,有本地备份和异地离线灾备两种,本地一般是为了回滚使用,而异地离线灾备则是为了 VPS 完全挂掉的时候,仍然不至于丢失所有的数据。考虑到 LinuxEye 的 LNMP 一键包提供了本地和远程备份的脚本,因此我选择本地和异地都备份一份以在保证高可用性的同时的可靠性。

备份脚本的操作并不是很复杂,这里已经有了操作说明,在这里也不再赘述。略微需要记录的一点,则是 Jailed SSH User 的实现。

一键包中的远程备份,是在本地完成备份打包之后,通过 rsync over SFTP 的方式同步至远程服务器,因此在远程服务器上必须有相对应的 SSH 用户才能操作。这里自然就会引出一个问题,由于无论是密码还是密钥登录,都需要将其存储在 VPS 之上,而我们自然不希望有人窃取了密码或者私钥之后登录到我们的备份服务器,因此这个备份用户本身的访问权限就应该被限制,也就是 Jailed SSH User,简而言之,Jailed SSH User 就是一个访问权限受限于特定目录树的用户,即使密码或者密钥被人窃取,也不用担心会给宿主机造成任何危害。接下来就谈一谈具体的实现。

Jailed SSH User 的创建教程用 Google 可以搜索到很多,我最终采用的是 StackOverflow 上提供的 Jailkit 的方案。具体步骤记录如下:

  • 下载 Jailkit 源码,编译安装
Download & Install:

http://olivier.sessink.nl/jailkit/index.html#download

# cd /tmp
# wget https://down.gloriousdays.pw/Tools/jailkit-2.19.tar.gz
# tar -zxvf jailkit-2.19.tar.gz
# cd jailkit-2.19
# ./configure
# make
# make install
  • 设置 Jail 根目录并完成初始化
# mkdir /home/jail
# chown root:root /home/jail

# jk_init -v /home/jail basicshell
# jk_init -v /home/jail netutils
# jk_init -v /home/jail ssh
# jk_init -v /home/jail jk_lsh
  • 创建一个用户并设置密码
# useradd -d /home/testuser -m testuser -s /bin/bash
# passwd testuser
  • 使用 Jailkit 将创建的用户移入 Jail 环境,如果需要建立更多的 Jailed User,在建立用户之后从这步开始即可
# jk_jailuser -m -j /home/jail testuser

Your /etc/passwd should contain something like this now:
testuser:x:1001:1001::/home/jail/./home/testuser:/usr/sbin/jk_chrootsh
  • 使用 jk_cp 命令复制 Bash 相关 Binary 进入 Jail 环境
# jk_cp -v -f /home/jail /bin/bash
  • 最后再做一些小的修改,将默认 shell 从 lsh 改成 bash
Now edit the /home/jail/etc/passwd file and make sure it contains something like this:
testuser:x:1001:1001::/home/testuser:/bin/bash
  • 之后在网站 VPS 上设置好备份配置,将备份脚本添加进入 crontab 自动执行
crontab -e 
0 1 * * * cd ~/lnmp;./backup.sh  > /dev/null 2>&1 &

Done!

如果还需要做一些维护,可以这样:

By using jk_update updates on the real system can be updated in the jail. A dry-run will >show what’s going on:
# jk_update -j /home/jail -d

 

搭建 NextCloud 服务器

之前折腾那些个 Low End VPS 的时候,弄到过一款 CentexHosting 的大硬盘的VPS,然后正好最近折腾有需求,就准备搭一个私有云在上面。一般来说,碰到私有云第一反应可能都会是 OwnCloud / SeaFile,不过我为什么要用 NextCloud 呢,还是因为我比较懒,NextCloud 有在线一键安装包,就不用麻烦去折腾配置了。

整体安装还是比较简单的,首先使用 LinuxEye 家的 LNMP 安装包,添加一个 nginx 虚拟主机。在这里不得不佩服一下这个一键包的作者,几乎所有的事情都可以通过他提供的脚本完成,比如我需要使用 Let’s Encrypt 签发 SSL 证书,只要用他的 addon.sh 安装 certbot 以后,在 vhost.sh 添加虚拟主机时就可以自动签发对应的证书,同时也配置好了自动续期的功能,如果有读者有类似需求,我在这里强烈推荐使用这个一键包,可以解决很多问题。

接下来就在 NextCloud 官网上下载 Web-Installer,放在虚拟主机对应的数据文件夹中,使用 phpMyAdmin 创建供私有云使用的用户和数据库,授予权限之后,填写在安装页面就可以了。

#安装过程不算特别顺利,NextCloud 似乎无法和 LNMP 一键包默认安装的 Zend OPcache 共存(报错“PHP 被设置为移除内联块, 这将导致多个核心应用无法访问”),需要使用 memcache 进行缓存。如何关掉 Zend OPcache也费了我一番周折,最后在 /usr/local/php/etc/php.d/ 目录下找到了它的配置文件,opcache.enable=0 关掉了缓存。不过这个仍然存在一定的问题,因为 NextCloud 还是需要缓存的,这点先按下不表。

  • Update:关于这个问题,其实还是可以使用 Zend OPcache 的,需要将 /usr/local/php/etc/php.d/ext-opcache.ini (oneinstack专用)中改为 opcache.save_comments=1 ,因为默认是0,改完重启 php-fpm 即可。

安装完成之后,却出现了 index.php 被跳转到 index.php/app/files 并且找不到文件的问题,Google 一下之后,官方论坛有人提到可能是 nginx 配置的问题,于是我就去查看了官方建议配置,但是却出现了 502 Bad Gateway 的问题。经查询,这种一般出现于 nginx 和 php-fpm 进程通信之间,观察了官方的配置文件之后,发现了这样一段:

upstream php-handler {
    server 127.0.0.1:9000;
    #server unix:/var/run/php5-fpm.sock;
}

我突然意识到,官方的配置文档是针对 php5 制作的,而我安装的是 php7,可能问题就出现在这里。于是试着换成了 /usr/local/nginx/conf/nginx.conf 中的 php 用法:

upstream php-handler {
     #server 127.0.0.1:9000;
     #server unix:/var/run/php5-fpm.sock;
     server unix:/dev/shm/php-cgi.sock;
}

#在执行了 service nginx reload 之后,神奇地可以用了,我也暂时也搞不清这是为什么,能正常运行了也是一件好事。

  • Update:关于这个跳转的问题,我认为是 nginx 配置 rewrite 规则的问题,如果需要解决这样的问题,应该严格按照官方建议 nginx 配置中的内容调整 location 开头的那些配置行。如果需要解决安装后 Nextcloud 有关 http header 问题的报错,则需要添加官方建议配置中的 add-header。这些在 Linuxeye 的一键包生成的配置中都没有解决,需要手动添加。

以下列出官方建议配置:

upstream php-handler {
    server 127.0.0.1:9000;
    #server unix:/var/run/php5-fpm.sock;
}

server {
    listen 80;
    server_name cloud.example.com;
    # enforce https
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name cloud.example.com;

    ssl_certificate /etc/ssl/nginx/cloud.example.com.crt;
    ssl_certificate_key /etc/ssl/nginx/cloud.example.com.key;

    # Add headers to serve security related headers
    # Before enabling Strict-Transport-Security headers please read into this
    # topic first.
    # add_header Strict-Transport-Security "max-age=15768000;
    # includeSubDomains; preload;";
    #
    # WARNING: Only add the preload option once you read about
    # the consequences in https://hstspreload.org/. This option
    # will add the domain to a hardcoded list that is shipped
    # in all major browsers and getting removed from this list
    # could take several months.
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;
    add_header X-Permitted-Cross-Domain-Policies none;

    # Path to the root of your installation
    root /var/www/nextcloud/;

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    # The following 2 rules are only needed for the user_webfinger app.
    # Uncomment it if you're planning to use this app.
    #rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
    #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json
    # last;

    location = /.well-known/carddav {
      return 301 $scheme://$host/remote.php/dav;
    }
    location = /.well-known/caldav {
      return 301 $scheme://$host/remote.php/dav;
    }

    # set max upload size
    client_max_body_size 512M;
    fastcgi_buffers 64 4K;

    # Enable gzip but do not remove ETag headers
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;

    # Uncomment if your server is build with the ngx_pagespeed module
    # This module is currently not supported.
    #pagespeed off;

    location / {
        rewrite ^ /index.php$uri;
    }

    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
        deny all;
    }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
        deny all;
    }

    location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) {
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param HTTPS on;
        #Avoid sending the security headers twice
        fastcgi_param modHeadersAvailable true;
        fastcgi_param front_controller_active true;
        fastcgi_pass php-handler;
        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }

    location ~ ^/(?:updater|ocs-provider)(?:$|/) {
        try_files $uri/ =404;
        index index.php;
    }

    # Adding the cache control header for js and css files
    # Make sure it is BELOW the PHP block
    location ~ \.(?:css|js|woff|svg|gif)$ {
        try_files $uri /index.php$uri$is_args$args;
        add_header Cache-Control "public, max-age=15778463";
        # Add headers to serve security related headers (It is intended to
        # have those duplicated to the ones above)
        # Before enabling Strict-Transport-Security headers please read into
        # this topic first.
        # add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
        #
        # WARNING: Only add the preload option once you read about
        # the consequences in https://hstspreload.org/. This option
        # will add the domain to a hardcoded list that is shipped
        # in all major browsers and getting removed from this list
        # could take several months.
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen;
        add_header X-Permitted-Cross-Domain-Policies none;
        # Optional: Don't log access to assets
        access_log off;
    }

    location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ {
        try_files $uri /index.php$uri$is_args$args;
        # Optional: Don't log access to other assets
        access_log off;
    }
}

不过,NextCloud 服务端报告目前仍然存在一定的问题:

  • PHP模块’文件信息’丢失. 我们强烈建议启用此模块以便mime类型检测取得最佳结果.
  • “X-Frame-Options” HTTP 头部没有配置和 “SAMEORIGIN” 的一样。这是一个潜在的安全或者隐私风险,我们调整
  • 内存缓存未配置。如果可用,请配置 memcache 来增强性能。更多信息请查看我们的文档 。

之后我再考虑如何解决,解决了之后也会在这里更新。

Update: Memcached 配置

根据官方文档,我选择 redis 作为 cache 模块,在 <site root>/config/config.php 中添加如下字段即可:

'memcache.local' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => array(
   'host' => 'localhost',
   'port' => 6379,
),

Update2:优化 php-fpm 内存占用

pm = ondemand
pm.max_children = 16
pm.start_servers = 11
pm.min_spare_servers = 8
pm.max_spare_servers = 16
pm.max_requests = 2048
pm.process_idle_timeout = 10s
request_terminate_timeout = 120
request_slowlog_timeout = 0

dd关于这个问题,如果 pm 配置为 dynamic 或者 static,php-fpm 会维护一个进程池,导致消耗大量内存,在小内存的 VPS 上,我们可以配置为 ondemand,就不需要那些额外开销了。