====== Xenial Xerus 설치 기록 ====== 미니서버를 2016년 5월 31일부로 14.04에서 16.04로 새로 설치하였다. 많이 변한 건 없는데, 해 놓은 게 많아서인지 설정할 것이 많았다. 특히 Nginx 변환 부분은 조금 힘들었음. 설치 기록을 남겨 본다. ===== Ubuntu 16.04 설치 ===== /dev/sdb1을 시스템, /dev/sda1을 주 저장소로 지정하였다. /dev/sda1을 이전과 마찬가지로 /media/storage(스토리지)에 마운트하여 사용하는 전략은 변함이 없다. 일부 읽기, 쓰기가 잦은 시스템의 디렉토리를 스토리지로 연결하는 전략을 쓴다. 예를 들면 /var/log, /tmp 은 심볼릭 링크 처리하고 실제로는 /media/storage/log, /media/storage/tmp가 역할을 대신한다. 우분투 설치는 매우 심플하게 한다. 스토리지를 기본으로 마운팅하게 하는 것 이외에는 그냥 있는 그대로의 설정을 사용하는 편이다. 사실 USB 스틱에서 부팅하는 방식이니 당연히 복잡하게 할 이유가 없다. 사용자 계정 패스워드를 입력하는 단계에서 패스워드를 평문으로 확인할 수 있도록 체크박스가 추가되었다는 점이 특이하다. 그 외에는 외견상 변한 점은 없다. 기본으로 삼바 서버와 OpenSSH 서버 패키지를 설치해 주고 설치를 마친다. 부팅 모두 문제 없다. 예전에는 기본 리포지터리를 다음이나 다른 곳으로 변경했었지만, 지금은 그것마저도 별 필요 없는 듯. ===== Database 설치 ===== 데이터베이스는 간결하게 mysql-server를 사용하기로 했다. apt-get install mysql-server ==== 데이터베이스 저장소 변경 ==== 시스템이 USB 스틱 메모리에 위치한지라, 여기에 계속 읽기/쓰기가 반복되는 것이 조금 껄끄럽다 생각했다. MySQL 5.5 -> 5.7로 마이그레이션하는 것이라 귀찮지만 미리 SQL 파일로 미리 데이터베이스를 모두 덤프해 두었다. 예전에는 눈치를 못챘거나 없었던 디렉토리가 생겼다. * /var/lib/mysql-files - 700 mysql:mysql * /var/lib/mysql-keyring - 700 mysql:mysql * /var/lib/mysql-upgrade - 755 root:root 이 세 디렉토리도 같이 옮기기로 결정. ==== AppArmor 설정 변경 ==== 나는 /tmp, /var/tmp를 모두 스토리지의 tmp 디렉토리로 심볼릭 링크를 걸었기 때문에, tmp 디렉토리까지도 설정을 변경해야 한다. 그러므로 ''/etc/apparmor.d/abstractions/user-tmp'' 파일의 마지막 부분에 다음 항목을 추가한다. # media/storage/tmp owner /media/storage/tmp/** rwkl, /media/storage/tmp/ rw, 다음으로 MySQL과 관련된 부분을 수정한다. ''/etc/apparmor.d/usr.sbin.mysqld'' # Allow data dir access /media/storage/mysql/ r, /media/storage/mysql/** rwk, # Allow data files dir access /media/storage/mysql-files/ r, /media/storage/mysql-files/** rwk, # Allow keyring dir access /media/storage/mysql-keyring/ r, /media/storage/mysql-keyring/** rwk, # Allow log file access /media/storage/log/mysql.err rw, /media/storage/log/mysql.log rw, /media/storage/log/mysql/ r, /media/storage/log/mysql/** rw, ==== my.cnf 변경 ==== ''/etc/mysql/mysql.conf.d/mysqld.cnf'' 버퍼 사이즈, 캐시 사이즈는 적절히 조정해줬다. 기준이 없으니 적절히 더 주는 정도? datadir = /media/storage/mysql tmpdir = /media/storage/tmp ===== PHP 7.0 ===== PHP 7.0이 기본으로 되었다. 쓰지 않을 이유가 없다. Nginx를 쓰기로 결정한 이상 FPM 방식을 사용해야 한다. ''apt-get install php php-fpm php-gd php-mcrypt php-mbstring'' FPM에서 발생하는 에러를 덤프하려면 ''/etc/php/7.0/fpm/pool.d/www.conf''' catch_workers_output = yes php.ini에는 여러 사이트에서 입을 모아 설정을 변경하려는 부분이 있다. ''/etc/php/7.0/php.ini'' cgi.fix_pathinfo=0 그리고 적절하게 업로드 사이즈를 변경해준다. upload_max_filesize = 64M post_max_size = 64M ==== pool 조정 ==== 특정 사이트의 PHP 실행 유저를 다르게 만들어 동작시킬 때 사용한다. ''/etc/php/7.0/fpm/pool.d'' 디렉토리의 www.conf 기본 파일을 적절히 편집해서 변경한다. nginx설정에서 원하는 사이트의 fastcgi 소켓 경로를 변경해 준다. opcache 문제도 있을 수 있는데, 이건 그냥 스킵. [[https://www.digitalocean.com/community/tutorials/how-to-host-multiple-websites-securely-with-nginx-and-php-fpm-on-ubuntu-14-04|참고 사이트]] ===== NGINX ===== 내 도메인이 주소가 아닌 직접 IP 접속은 같은 공유기 안의 주소가 아니면 오지 못하도록 막을 필요가 있다. ''/etc/nginx/sites-available/default'' # allow only localhost allow 192.168.0.0/24; allow 192.168.10.0/24; deny all; ===== 웹 애플리케이션 세팅 ===== ==== PhpMyAdmin ==== ''apt-get install phpmyadmin'' ''/media/storage/www-data/conf.d/phpmyadmin.conf'' location /phpmyadmin { alias /usr/share/phpmyadmin; index index.php index.html index.htm; location ~ ^/phpmyadmin/(.+\.php)$ { root /usr/share; fastcgi_pass unix:/run/php/php7.0-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } 이 파일을 default에서 삽입한다. # Include PhpMyAdmin address include /media/storage/www-data/conf.d/phpmyadmin.conf; ==== Dokuwiki ==== # Nginx Configuration # 아래 설정은 https 적용 이후 http -> https 이동에 사용됨. server { listen 80; server_name wiki.changwoo.pe.kr; return 301 https://$server_name$request_uri; } server { listen 80; server_name wiki.changwoo.pe.kr; client_max_body_size 32M; client_body_buffer_size 256k; root /media/storage/www-data/changwoo.pe.kr/wiki; index doku.php; # Remember to comment the below out when you're installing, and uncomment it when done. location ~ /(data/|conf/|bin/|inc/|install.php) { deny all; } # Uncomment this prevents images being displayed ! #location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { # expires 31536000s; # add_header Pragma "public"; # add_header Cache-Control "max-age=31536000, public, must-revalidate, proxy-revalidate"; # log_not_found off; #} location / { try_files $uri $uri/ @dokuwiki; } location @dokuwiki { rewrite ^/_media/(.*) /lib/exe/fetch.php?media=$1 last; rewrite ^/_detail/(.*) /lib/exe/detail.php?media=$1 last; rewrite ^/_export/([^/]+)/(.*) /doku.php?do=export_$1&id=$2 last; rewrite ^/(.*) /doku.php?id=$1&$args last; } location ~ \.php { include snippets/fastcgi-php.conf; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; fastcgi_pass unix:/run/php/php7.0-fpm.sock; } location ~ /\.ht { deny all; } } nginx라면 복구 이후 멋진 URL에서 .htaccess 방식을 선택해야 문서가 올바르게 보인다. ==== WordPress ==== 이 녀석은 조금 복잡하다. # Global restrictions configuration file. # Designed to be included in any server {} block. location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { allow all; log_not_found off; access_log off; } # Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac). # Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban) location ~ /\. { deny all; } # Deny access to any files with a .php extension in the uploads directory # Works in sub-directory installs and also in multisite network # Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban) location ~* /(?:uploads|files)/.*\.php$ { deny all; } # WordPress single site rules. # Designed to be included in any server {} block. # This order might seem weird - this is attempted to match last if rules below fail. # http://wiki.nginx.org/HttpCoreModule location / { try_files $uri $uri/ /index.php?$args; } # Add trailing slash to */wp-admin requests. rewrite /wp-admin$ $scheme://$host$uri/ permanent; # Directives to send expires headers and turn off 404 error logging. location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ { access_log off; log_not_found off; expires max; } # Uncomment one of the lines below for the appropriate caching plugin (if used). #include global/wordpress-wp-super-cache.conf; #include global/wordpress-w3-total-cache.conf; # Pass all .php files onto a php-fpm/php-fcgi server. location ~ [^/]\.php(/|$) { fastcgi_split_path_info ^(.+?\.php)(/.*)$; if (!-f $document_root$fastcgi_script_name) { return 404; } # This is a robust solution for path info security issue and works with "cgi.fix_pathinfo = 1" in /etc/php.ini (default) # include fastcgi_params; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # fastcgi_intercept_errors on; # fastcgi_pass php; include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.0-fpm.sock; } # 아래 설정은 https 적용 이후 http -> https 이동에 사용됨. server { listen 80; server_name wiki.changwoo.pe.kr; return 301 https://$server_name$request_uri; } server { server_name blog.changwoo.pe.kr; root /media/storage/www-data/changwoo.pe.kr/wordpress; index index.php; # wp-login.php, wp-admin 접근을 IP로 제한 (단, wp-ajax.php는 AJAX를 활용해야 하므로 허용) location ~ ^/(wp-admin(?!/admin-ajax\.php)|wp-login.php) { allow 192.168.0.0/24; deny all; include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.0-fpm.sock; } include /media/storage/www-data/conf.d/wordpress-restrictions.conf; include /media/storage/www-data/conf.d/wordpress.conf; } ==== Ampache ==== 그동안 모바일 기기에서 제대로 재생이 되지 않는 문제가 있었다가, nginx 설정을 변경해 줌으로써 해결하였다. 아래는 성공한 설정 텍스트. [[https://github.com/ampache/ampache/wiki/Installation#nginx|이 쪽의 설정]]을 가져와 문제가 되는 부분을 적절히 수정한 것. server { # listen to #listen [::]:used_port; #ssl; ipv6 optional with ssl enabled listen 80; #ssl; ipv4 optional with ssl enabled server_name stream.changwoo.pe.kr; charset utf-8; # Logging, error_log mode [notice] is necessary for rewrite_log on, # (very usefull if rewrite rules do not work as expected) error_log /var/log/ampache/error.log; #notice; access_log /var/log/ampache/access.log; # rewrite_log on; # only optional for ssl encryption enabled: Path to certificate/key # ssl_certificate /etc/ssl/certs/cert.crt; # ssl_certificate_key /etc/ssl/private/key.key; root /media/storage/www-data/changwoo.pe.kr/ampache; index index.php; # Somebody said this helps, in my setup it doesn't prevent temporary saving in files proxy_max_temp_file_size 0; # Rewrite rule for Subsonic backend if ( !-d $request_filename ) { rewrite ^/rest/(.*).view$ /rest/index.php?action=$1 last; rewrite ^/rest/fake/(.+)$ /play/$1 last; } # Rewrite rule for Channels if (!-d $request_filename){ rewrite ^/channel/([0-9]+)/(.*)$ /channel/index.php?channel=$1&target=$2 last; } # Beautiful URL Rewriting # rewrite ^/play/ssid/(.*)/type/(\w+)/oid/([0-9]+)/uid/([0-9]+)/name/(.*)$ /play/index.php?ssid=$1&type=$2&oid=$3&uid=$4&name=$5 last; # rewrite ^/play/ssid/(.*)/type/(\w+)/oid/([0-9]+)/uid/([0-9]+)/client/(.*)/noscrobble/([0-1])/name/(.*)$ /play/index.php?ssid=$1&type=$2&oid=$3&uid=$4&client=$5&noscrobble=$6&name=$7 last; # rewrite ^/play/ssid/(.*)/type/(.*)/oid/([0-9]+)/uid/([0-9]+)/client/(.*)/noscrobble/([0-1])/player/(.*)/name/(.*)$ /play/index.php?ssid=$1&type=$2&oid=$3&uid=$4&client=$5&noscrobble=$6&player=$7&name=$8 last; # rewrite ^/play/ssid/(.*)/type/(.*)/oid/([0-9]+)/uid/([0-9]+)/client/(.*)/noscrobble/([0-1])/transcode_to/(w+)/bitrate/([0-9]+)/player/(.*)/name/(.*)$ /play/index.php?ssid=$1&type=$2&oid=$3&uid=$4&client=$5&noscrobble=$6&transcode_to=$7&bitrate=$8&player=$9&name=$10 last; # Subsonic Apps (not working!) # rewrite ^/play/ssid/(.*)/type/(.*)/oid/([0-9]+)/uid/([0-9]+)/client/(.*)/noscrobble/([0-1])/content_length/(.*)/player/(.*)/name/(.*)$ /play/index.php?ssid=$1&type=$2&oid=$3&uid=$4&client=$5&noscrobble=$6&content_length=$7&player=$8&name=$9 redirect; # rewrite ^/play/ssid/(.*)/type/(.*)/oid/([0-9]+)/uid/([0-9]+)/client/(.*)/noscrobble/([0-1])/bitrate/([0-9]+)/player/(.*)/name/(.*)$ /play/index.php?ssid=$1&type=$2&oid=$3&uid=$4&client=$5&noscrobble=$6&bitrate=$7&player=$8&name=$9 redirect; # rewrite ^/play/ssid/(.*)/type/(.*)/oid/([0-9]+)/uid/([0-9]+)/client/(.*)/noscrobble/([0-1])/player/(.*)/name/(.*)$ /play/index.php?ssid=$1&type=$2&oid=$3&uid=$4&client=$5&noscrobble=$6&player=$7&name=$8 redirect; # the following line was needed for me to get downloads of single songs to work rewrite ^/play/ssid/(.*)/type/(.*)/oid/([0-9]+)/uid/([0-9]+)/action/(.*)/name/(.*)$ /play/index.php?ssid=$1&type=$2&oid=$3&uid=$4action=$5&name=$6 last; location /play/ssid { if (!-e $request_filename) { # Subsonic Apps rewrite ^/play/ssid/(.*)/type/(.*)/oid/([0-9]+)/uid/([0-9]+)/client/(.*)/noscrobble/([0-1])/content_length/(.*)/player/(.*)/name/(.*)$ /play/index.php?ssid=$1&type=$2&oid=$3&uid=$4&client=$5&noscrobble=$6&content_length=$7&player=$8&name=$9 last; rewrite ^/play/ssid/(.*)/type/(.*)/oid/([0-9]+)/uid/([0-9]+)/client/(.*)/noscrobble/([0-1])/bitrate/([0-9]+)/player/(.*)/name/(.*)$ /play/index.php?ssid=$1&type=$2&oid=$3&uid=$4&client=$5&noscrobble=$6&bitrate=$7&player=$8&name=$9 last; rewrite ^/play/ssid/(.*)/type/(.*)/oid/([0-9]+)/uid/([0-9]+)/client/(.*)/noscrobble/([0-1])/player/(.*)/name/(.*)$ /play/index.php?ssid=$1&type=$2&oid=$3&uid=$4&client=$5&noscrobble=$6&player=$7&name=$8 last; break; } } location /play { if (!-e $request_filename) { rewrite ^/play/art/([^/]+)/([^/]+)/([0-9]+)/thumb([0-9]*)\.([a-z]+)$ /image.php?object_type=$2&object_id=$3&auth=$1; break; } rewrite ^/([^/]+)/([^/]+)(/.*)?$ /play/$3?$1=$2; rewrite ^/(/[^/]+|[^/]+/|/?)$ /play/index.php last; break; } location /rest { limit_except GET POST { deny all; } } location ^~ /bin/ { deny all; return 403; } location ^~ /config/ { deny all; return 403; } location / { limit_except GET POST HEAD{ deny all; } } location ~ ^/.*.php { try_files $uri = 404; fastcgi_index index.php; # sets the timeout for requests in [s] , 60s are normally enough fastcgi_read_timeout 600s; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # Mitigate HTTPOXY https://httpoxy.org/ fastcgi_param HTTP_PROXY ""; # has to be set to on if encryption (https) is used: # fastcgi_param HTTPS on; fastcgi_split_path_info ^(.+?\.php)(/.*)$; # chose as your php-fpm is configured to listen on fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; # fastcgi_pass 127.0.0.1:8000/; } # Rewrite rule for WebSocket location /ws { rewrite ^/ws/(.*) /$1 break; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_pass http://127.0.0.1:8100/; } } ==== Python 계열 세팅 ==== 내가 운용 중인 모든 애플리케이션은 Python3로 작성되어 있으니, 그 쪽으로 세팅을 맞춘다. apt install python3-pip virtualenv, virtualenvwrapper도 다시 설정해 주자. pip3 install virtualenv virtualenvwrapper uwsgi는 시스템 쪽으로 맞춰 줬다. pip3 install uwsgi === Nginx === # Nginx configuration for miniserver-apps upstream django { server unix:// } server { listen 80; server_name apps.changwoo.pe.kr; charset utf-8; client_max_body_size 8M; location /favicon.ico { access_log off; log_not_found off; } location /static { alias /static; } location / { uwsgi_pass django; include uwsgi_params; } } === uWSGI === 앱이 하나일 때는 아래와 같이 간단하게 master로 돌렸다. [uwsgi] # Djnago project base directory chdir = # WSGI Python module module = miniserver.wsgi # Virtualenv path home = master = true processes = 4 socket = vacuum = true chmod-socket = 664 chown-socket = owner:group enable-threads = true pidfile = daemonize = 그러나 복수의 앱을 운영해야 할 시점이 생기자 엡퍼러(emperor) 모드가 필요해졌다. 엠퍼러 모드는 간단하게 이렇게 쓸 수 있다. uid=owner daemonize= emperor= 에는 그룹으로 돌릴 ini 파일들을 넣으면 된다. 즉 miniserver-apps.ini 파일 같은 것을 그대로 이 디렉토리에 넣으면 되는데, 이 때 주의할 점은 몇몇 설정들은 이미 엠퍼러에서 진행되었으므로 삭제해야 한다. 예를 들어 miniserver-apps.ini에서 demonize, uid 같은 설정값은 에러를 낼 수 있다. === rc.local === 매번 부팅때마다 돌려 줘야 하므로, /usr/local/bin/uwsgi --ini ini_file.ini 자 이렇게 대략 세팅해 주면 파이썬은 돌아간다. uwsgi --stop /tmp/project-master.pid uwsgi --reload /tmp/project-master.pid kill -HUP `cat /tmp/project-master.pid` killall -s INT uwsgi ===== 사용자 계정 생성 ===== changwoo 계정 생성 useradd -m -d /media/storage/changwoo -s /bin/bash ===== Samba ===== 삼바는 이미 설치되어 있으므로 아주 간단하게 내부에서 공유 디렉토리만 되도록 설정 추가한다. ''/etc/samba/smb.conf'' [changwoo] path = /media/storage/changwoo writable = yes create mask = 0644 directory mask = 0755 심볼릭 링크를 추가하기 위해 다음과 같은 세팅을 주었다((http://unix.stackexchange.com/questions/5120/how-do-you-make-samba-follow-symlink-outside-the-shared-path)) [global] allow insecure wide links = yes [share] follow symlinks = yes wide links = yes service smbd restart ===== Dropbox ===== #!/bin/sh # # Copied from http://forums.dropbox.com/topic.php?id=38529#post-414344 # Modified by jay@gooby.org (@jaygooby on Twitter) ### BEGIN INIT INFO # Provides: dropbox # Required-Start: $local_fs $remote_fs $network $syslog $named # Required-Stop: $local_fs $remote_fs $network $syslog $named # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # X-Interactive: false # Short-Description: dropbox service ### END INIT INFO # dropbox service DROPBOX_USERS="changwoo" start() { echo "Starting dropbox..." for dbuser in $DROPBOX_USERS; do HOMEDIR=$(getent passwd $dbuser | cut -d: -f6) DAEMON=$(find $HOMEDIR/.dropbox-dist/dropbox-lnx.* -name dropboxd) if [ -x $DAEMON ]; then HOME="$HOMEDIR" start-stop-daemon -b -o -c $dbuser -S -u $dbuser -x $DAEMON -p "$HOMEDIR/.dropbox/dropbox.pid" fi done } stop() { echo "Stopping dropbox..." for dbuser in $DROPBOX_USERS; do HOMEDIR=$(getent passwd $dbuser | cut -d: -f6) DAEMON=$(find $HOMEDIR/.dropbox-dist/dropbox-lnx.* -name dropbox) if [ -x $DAEMON ]; then start-stop-daemon -o -c $dbuser -K -u $dbuser -x $DAEMON fi done } status() { for dbuser in $DROPBOX_USERS; do dbpid=$(pgrep -u $dbuser dropbox) if [ -z $dbpid ] ; then echo "dropboxd for USER $dbuser: not running." else echo "dropboxd for USER $dbuser: running (pid $dbpid)" fi done } case "$1" in start) start ;; stop) stop ;; restart|reload|force-reload) stop start ;; status) status ;; *) echo "Usage: /etc/init.d/dropbox {start|stop|reload|force-reload|restart|status}" exit 1 esac exit 0 ''/etc/init.d/dropbox'' ===== Torrent ===== 언제나 그렇듯 deluge를 애용한다. apt-get install deluge-common deluge-web deluged 같이 데몬 스크립트도 설치되지만, 이 스크립트는 web UI를 기본 지원하지 않아 불만족스럽다. 기존 스크립트로 대체한다. ''/etc/default/deluge-daemon'' # Configuration for /etc/init.d/deluge-daemon # The init.d script will only run if this variable non-empty. DELUGED_USER="changwoo" # !!!CHANGE THIS!!!! # Should we run at startup? RUN_AT_STARTUP="YES" ''/etc/init.d/deluge-daemon'' #!/bin/sh ### BEGIN INIT INFO # Provides: deluge-daemon # Required-Start: $local_fs $remote_fs # Required-Stop: $local_fs $remote_fs # Should-Start: $network # Should-Stop: $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Daemonized version of deluge and webui. # Description: Starts the deluge daemon with the user specified in # /etc/default/deluge-daemon. ### END INIT INFO # Author: Adolfo R. Brandes # Updated by: Jean-Philippe "Orax" Roemer PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DESC="Deluge Daemon" NAME1="deluged" NAME2="deluge" DAEMON1=/usr/bin/deluged DAEMON1_ARGS="-d -c /media/storage/changwoo/.config/deluge -L info -l /media/storage/changwoo/.config/deluge/deluge.log" # Consult `man deluged` for more options DAEMON2=/usr/bin/deluge-web DAEMON2_ARGS="" # Consult `man deluge-web` for more options PIDFILE1=/var/run/$NAME1.pid PIDFILE2=/var/run/$NAME2.pid UMASK=022 # Change this to 0 if running deluged as its own user PKGNAME=deluge-daemon SCRIPTNAME=/etc/init.d/$PKGNAME # Exit if the package is not installed [ -x "$DAEMON1" -a -x "$DAEMON2" ] || exit 0 # Read configuration variable file if it is present [ -r /etc/default/$PKGNAME ] && . /etc/default/$PKGNAME # Load the VERBOSE setting and other rcS variables [ -f /etc/default/rcS ] && . /etc/default/rcS # Define LSB log_* functions. # Depend on lsb-base (>= 3.0-6) to ensure that this file is present. . /lib/lsb/init-functions if [ -z "$RUN_AT_STARTUP" -o "$RUN_AT_STARTUP" != "YES" ] then log_warning_msg "Not starting $PKGNAME, edit /etc/default/$PKGNAME to start it." exit 0 fi if [ -z "$DELUGED_USER" ] then log_warning_msg "Not starting $PKGNAME, DELUGED_USER not set in /etc/default/$PKGNAME." exit 0 fi # # Function to verify if a pid is alive # is_alive() { pid=`cat $1` > /dev/null 2>&1 kill -0 $pid > /dev/null 2>&1 return $? } # # Function that starts the daemon/service # do_start() { # Return # 0 if daemon has been started # 1 if daemon was already running # 2 if daemon could not be started is_alive $PIDFILE1 RETVAL1="$?" if [ $RETVAL1 != 0 ]; then rm -f $PIDFILE1 start-stop-daemon --start --background --quiet --pidfile $PIDFILE1 --make-pidfile \ --exec $DAEMON1 --chuid $DELUGED_USER --user $DELUGED_USER --umask $UMASK -- $DAEMON1_ARGS RETVAL1="$?" else is_alive $PIDFILE2 RETVAL2="$?" [ "$RETVAL2" = "0" -a "$RETVAL1" = "0" ] && return 1 fi is_alive $PIDFILE2 RETVAL2="$?" if [ $RETVAL2 != 0 ]; then sleep 2 rm -f $PIDFILE2 start-stop-daemon --start --background --quiet --pidfile $PIDFILE2 --make-pidfile \ --exec $DAEMON2 --chuid $DELUGED_USER --user $DELUGED_USER --umask $UMASK -- $DAEMON2_ARGS RETVAL2="$?" fi [ "$RETVAL1" = "0" -a "$RETVAL2" = "0" ] || return 2 } # # Function that stops the daemon/service # do_stop() { # Return # 0 if daemon has been stopped # 1 if daemon was already stopped # 2 if daemon could not be stopped # other if a failure occurred start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --user $DELUGED_USER --pidfile $PIDFILE2 RETVAL2="$?" start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --user $DELUGED_USER --pidfile $PIDFILE1 RETVAL1="$?" [ "$RETVAL1" = "2" -o "$RETVAL2" = "2" ] && return 2 rm -f $PIDFILE1 $PIDFILE2 [ "$RETVAL1" = "0" -a "$RETVAL2" = "0" ] && return 0 || return 1 } case "$1" in start) [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME1" do_start case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; stop) [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME1" do_stop case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; restart|force-reload) log_daemon_msg "Restarting $DESC" "$NAME1" do_stop case "$?" in 0|1) do_start case "$?" in 0) log_end_msg 0 ;; 1) log_end_msg 1 ;; # Old process is still running *) log_end_msg 1 ;; # Failed to start esac ;; *) # Failed to stop log_end_msg 1 ;; esac ;; *) echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2 exit 3 ;; esac : 패키지로 설치된 /etc/init.d/deluged는 실행되지 않도록 수정. /etc/init.d# systemctl disable deluged chmod -x /etc/init.d/deluged 동작하도록 재설정 systemctl daemon-reload service deluge-daemon start ===== CronTab ===== ==== python-onedrive ==== 이 프로젝트는 폐기되었지만, 간단하게 쓰고 있었고 당분간은 동작하므로 그냥 쓴다. apt install python-pip requests pyYAML ''~/.lcrc''에 client id, secret을 설정하고 onedrive-cli quota ==== 스크립트들 ==== * dokuwiki_autobackup: 도쿠위키 백업 * wp_backup: 워드프레스 백업 도쿠위키는 월요일 오전 4시에, 워드프레스는 월요일 오전 5시에 백업. 0 4 * * 1 /media/storage/changwoo/Dropbox/MiniServer/scripts/dokuwiki_autobackup 0 5 * * 1 /media/storage/changwoo/Dropbox/MiniServer/scripts/wp_backup.sh ===== Resilio-Sync ===== [[https://www.resilio.com/ | Resilio-Sync ]]로 비트토렌트 방식의 싱크. [[project:btsyncforrpi | 라즈베리 파이에서 BitTorrentSync로 데이터 동기화하기 ]] 같은 문서로도 작성한 바가 있다. 이게 이름이 바뀌었다. 가정용은 무료이니 나같이 그냥 비디오 디렉토리 공유하는 수준에서는 괜찮은 선택인 것 같다. deb 패키지가 제공되니 깔아 주면 그만이다. service resilio-sync start 명령으로 실행하면 되는데, 변경은 다음과 같은 명령으로 $ sudo systemctl edit resilio-sync.service [Service] User=changwoo Group=changwoo PIDFile= PIDFile=/home/changwoo/.config/resilio-sync/sync.pid ExecStartPre= ExecStartPre=/bin/mkdir -p /home/changwoo/.config/resilio-sync ExecStartPre=/bin/chown -R changwoo:changwoo /home/changwoo/.config/resilio-sync ExecStart= ExecStart=/usr/bin/rslsync --config /home/changwoo/.config/resilio-sync/config.json systemctl edit 명령은 파일 자체를 변경하는 것이 아니라 overriding 하는 방식이다.그리고 override 할 때 기존 명령어는 한번 비워주는 작업이 필요하다. 그래서 "''ExexStart=''" 같은 라인이 생기는 것이다. 저것이 없으면 에러. $ sudo systemctl cat resilio-sync.service [Unit] Description=Resilio Sync service Documentation=https://help.getsync.com/ After=network.target network-online.target [Service] Type=forking User=rslsync Group=rslsync UMask=0002 Restart=on-failure PermissionsStartOnly=true PIDFile=/var/run/resilio-sync/sync.pid ExecStartPre=/bin/mkdir -p /var/run/resilio-sync ExecStartPre=/bin/chown -R rslsync:rslsync /var/run/resilio-sync ExecStart=/usr/bin/rslsync --config /etc/resilio-sync/config.json [Install] WantedBy=multi-user.target # /etc/systemd/system/resilio-sync.service.d/override.conf [Service] User=changwoo Group=changwoo PIDFile= PIDFile=/home/changwoo/.config/resilio-sync/sync.pid ExecStartPre= ExecStartPre=/bin/mkdir -p /home/changwoo/.config/resilio-sync ExecStartPre=/bin/chown -R changwoo:changwoo /home/changwoo/.config/resilio-sync ExecStart= ExecStart=/usr/bin/rslsync --config /home/changwoo/.config/resilio-sync/config.json 이렇게 덧붙여지는 것을 참고하자. ===== SSL 설비 ===== 이제는 필수로 구비하자. Let's Encrypt가 있다. 아래의 가이드를 따라하면 어렵지 않다. * https://certbot.eff.org/#ubuntuxenial-nginx * http://riseshia.github.io/2016/10/16/certbot-let-s-encrypt.html 3개월마다 갱신해야 하는데, 나는 아직 자동 갱신을 하지는 않았다. 나중에 확인하고 달아 보도록 하자.