From 5d4935812ac8b3da8dd0150b33fe662e17c48ed1 Mon Sep 17 00:00:00 2001 From: Elie Date: Mon, 11 Aug 2014 21:18:09 -0400 Subject: [PATCH] Install completed --- conf/nginx.conf | 30 ++- conf/seafile-server | 44 +++++ conf/seafile-server.conf | 10 + manifest.json | 16 ++ scripts/install | 42 +++- scripts/remove | 4 +- sources/check_init_admin.py | 371 ++++++++++++++++++++++++++++++++++++ sources/setup-seafile.sh | 46 +---- 8 files changed, 511 insertions(+), 52 deletions(-) create mode 100644 conf/seafile-server create mode 100644 conf/seafile-server.conf create mode 100644 sources/check_init_admin.py diff --git a/conf/nginx.conf b/conf/nginx.conf index 3f9a26b..b4307ad 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -4,4 +4,32 @@ location PATHTOCHANGE { rewrite ^ https://$server_name$request_uri? permanent; } client_max_body_size 10G; -} \ No newline at end of file + + + fastcgi_pass 127.0.0.1:SEAHUB_PORT; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_script_name; + + fastcgi_param SERVER_PROTOCOL $server_protocol; + fastcgi_param QUERY_STRING $query_string; + fastcgi_param REQUEST_METHOD $request_method; + fastcgi_param CONTENT_TYPE $content_type; + fastcgi_param CONTENT_LENGTH $content_length; + fastcgi_param SERVER_ADDR $server_addr; + fastcgi_param SERVER_PORT $server_port; + fastcgi_param SERVER_NAME $server_name; + fastcgi_param HTTPS on; + +} + +location ~* ^PATHTOCHANGE/media/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt|woff|ttf))$ { + root ALIASTOCHANGEseafile-server-latest/; +} + +location /seafhttp { + rewrite ^/seafhttp(.*)$ $1 break; + proxy_pass http://127.0.0.1:SEAFILE_FILESERVER_PORT; + client_max_body_size 0; +} + + diff --git a/conf/seafile-server b/conf/seafile-server new file mode 100644 index 0000000..1b9dfd6 --- /dev/null +++ b/conf/seafile-server @@ -0,0 +1,44 @@ +#!/bin/bash + +# Change the value of "user" to your linux user name +user=root + +# Change the value of "seafile_dir" to your path of seafile installation +seafile_dir=SEAFILE_DIR +script_path=${seafile_dir}/seafile-server-latest +seafile_init_log=${seafile_dir}/logs/seafile.init.log +seahub_init_log=${seafile_dir}/logs/seahub.init.log + +# Change the value of fastcgi to true if fastcgi is to be used +fastcgi=true +# Set the port of fastcgi, default is 8000. Change it if you need different. +fastcgi_port=SEAHUB_PORT + +case "$1" in + start) + sudo -u ${user} ${script_path}/seafile.sh start >> ${seafile_init_log} + if [ $fastcgi = true ]; + then + sudo -u ${user} ${script_path}/seahub.sh start-fastcgi ${fastcgi_port} >> ${seahub_init_log} + else + sudo -u ${user} ${script_path}/seahub.sh start >> ${seahub_init_log} + fi + ;; + restart) + sudo -u ${user} ${script_path}/seafile.sh restart >> ${seafile_init_log} + if [ $fastcgi = true ]; + then + sudo -u ${user} ${script_path}/seahub.sh restart-fastcgi ${fastcgi_port} >> ${seahub_init_log} + else + sudo -u ${user} ${script_path}/seahub.sh restart >> ${seahub_init_log} + fi + ;; + stop) + sudo -u ${user} ${script_path}/seafile.sh $1 >> ${seafile_init_log} + sudo -u ${user} ${script_path}/seahub.sh $1 >> ${seahub_init_log} + ;; + *) + echo "Usage: /etc/init.d/seafile-server {start|stop|restart}" + exit 1 + ;; +esac \ No newline at end of file diff --git a/conf/seafile-server.conf b/conf/seafile-server.conf new file mode 100644 index 0000000..9ca371c --- /dev/null +++ b/conf/seafile-server.conf @@ -0,0 +1,10 @@ +start on (runlevel [2345]) +stop on (runlevel [016]) + +pre-start script +/etc/init.d/seafile-server start +end script + +post-stop script +/etc/init.d/seafile-server stop +end script \ No newline at end of file diff --git a/manifest.json b/manifest.json index fcd92ff..d93b1aa 100644 --- a/manifest.json +++ b/manifest.json @@ -36,6 +36,22 @@ }, "example": "Seafile", "default": "Seafile" + }, + { + "name": "admin_email", + "ask": { + "en": "Choose an email" + }, + "example": "admin@domain.com", + "default": "admin@domain.com" + }, + { + "name": "admin_password", + "ask": { + "en": "Choose a password" + }, + "example": "123456", + "default": "123456" } ] } diff --git a/scripts/install b/scripts/install index 0c7173d..154b5b2 100644 --- a/scripts/install +++ b/scripts/install @@ -2,6 +2,8 @@ domain=$1 path=$2 server_name=$3 +admin_email=$4 +admin_password=$5 final_path=/var/www/seafile seafile_data=$final_path/seafile-data seafile_version=3.1.1 @@ -13,14 +15,15 @@ if [[ ! $? -eq 0 ]]; then fi # Check dependencies -sudo apt-get install -y python2.7 python-setuptools python-simplejson python-imaging python-mysqldb +sudo apt-get install -y python2.7 python-setuptools python-simplejson python-imaging python-mysqldb sqlite3 # Copy files to the right place sudo mkdir -p $final_path sudo mkdir -p $final_path/installed +sudo mkdir -p $final_path/logs sudo mkdir -p $final_path/seafile-data sudo mkdir -p $final_path/seafile-server-$seafile_version -sudo tar xvzf ../sources/'seafile-server_'$seafile_version'_x86-64.tar' +sudo tar xzf ../sources/'seafile-server_'$seafile_version'_x86-64.tar' sudo mv seafile-server-$seafile_version/* $final_path/seafile-server-$seafile_version sudo mv ../sources/'seafile-server_'$seafile_version'_x86-64.tar' $final_path/installed @@ -30,7 +33,13 @@ sudo chown -R www-data: $final_path # Find available ports ccnet_port=10001 seafile_port=12001 -seahub_port=8082 +seafile_fileserver_port=8082 +seahub_port=8000 + +sudo yunohost app checkport $seahub_port +sudo yunohost app checkport $seafile_fileserver_port +sudo yunohost app checkport $seafile_port +sudo yunohost app checkport $ccnet_port # Modify install script with parameters sed -i "s@SERVER_NAME@$server_name@g" ../sources/setup-seafile.sh @@ -38,23 +47,44 @@ sed -i "s@DOMAIN@$domain@g" ../sources/setup-seafile.sh sed -i "s@CCNET_PORT@$ccnet_port@g" ../sources/setup-seafile.sh sed -i "s@SEAFILE_DATA@$seafile_data@g" ../sources/setup-seafile.sh sed -i "s@SEAFILE_PORT@$seafile_port@g" ../sources/setup-seafile.sh -sed -i "s@SEAHUB_PORT@$seahub_port@g" ../sources/setup-seafile.sh +sed -i "s@SEAFILE_FILESERVER_PORT@$seafile_fileserver_port@g" ../sources/setup-seafile.sh +sed -i "s/ADMIN_EMAIL/$admin_email/g" ../sources/check_init_admin.py +sed -i "s/ADMIN_PASSWORD/$admin_password/g" ../sources/check_init_admin.py # Run install script +sudo cp ../sources/check_init_admin.py $final_path/seafile-server-$seafile_version sudo cp ../sources/setup-seafile.sh $final_path/seafile-server-$seafile_version sudo chmod +x $final_path/seafile-server-$seafile_version/setup-seafile.sh sudo $final_path/seafile-server-$seafile_version/setup-seafile.sh -# Start Seafile Server +# Update config +sudo sed -i "s@:8000@$path@g" $final_path/ccnet/ccnet.conf +echo 'SERVE_STATIC = False' | sudo tee -a $final_path/seahub_settings.py +echo 'MEDIA_URL = "'$path'/media/"' | sudo tee -a $final_path/seahub_settings.py +echo 'SITE_ROOT = "'$path'/"' | sudo tee -a $final_path/seahub_settings.py +echo 'FILE_SERVER_ROOT = "http://'$domain$path'"' | sudo tee -a $final_path/seahub_settings.py +# Symlink for media ( because only $path is accessible, not /seahub ) +sudo ln -s $final_path/seafile-server-$seafile_version/seahub/media/ $final_path/seafile-server-$seafile_version/seafile/media # Add Seafile Server to startup -# TODO +sed -i "s@SEAHUB_PORT@$seahub_port@g" ../conf/seafile-server +sed -i "s@SEAFILE_DIR@$final_path@g" ../conf/seafile-server +sudo cp ../conf/seafile-server /etc/init.d +sudo chmod +x /etc/init.d/seafile-server +sudo cp ../conf/seafile-server.conf /etc/init +sudo update-rc.d seafile-server defaults +# Start Seafile Server +sudo $final_path/seafile-server-$seafile_version/seafile.sh start +sudo $final_path/seafile-server-$seafile_version/seahub.sh start-fastcgi $seahub_port # Modify Nginx configuration file and copy it to Nginx conf directory sed -i "s@PATHTOCHANGE@$path@g" ../conf/nginx.conf sed -i "s@ALIASTOCHANGE@$final_path/@g" ../conf/nginx.conf +sed -i "s@SEAHUB_PORT@$seahub_port@g" ../conf/nginx.conf +sed -i "s@SEAFILE_FILESERVER_PORT@$seafile_fileserver_port@g" ../conf/nginx.conf +sed -i "s@SEAFILE_PATH@$final_path@g" ../conf/nginx.conf sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/seafile.conf diff --git a/scripts/remove b/scripts/remove index 9b456dd..8d26573 100644 --- a/scripts/remove +++ b/scripts/remove @@ -6,4 +6,6 @@ sudo ./seafile.sh stop sudo ./seahub.sh stop sudo rm -rf /var/www/seafile -sudo rm -f /etc/nginx/conf.d/$domain.d/seafile.conf \ No newline at end of file +sudo rm -f /etc/nginx/conf.d/$domain.d/seafile.conf +sudo rm -f /etc/init.d/seafile-server +sudo rm -f /etc/init/seafile-server.conf \ No newline at end of file diff --git a/sources/check_init_admin.py b/sources/check_init_admin.py new file mode 100644 index 0000000..31d586a --- /dev/null +++ b/sources/check_init_admin.py @@ -0,0 +1,371 @@ +#coding: UTF-8 + +'''This script would check if there is admin, and prompt the user to create a new one if non exist''' + +import sys +import os +import time +import re +import shutil +import glob +import subprocess +import hashlib +import getpass +import uuid +import warnings + +from ConfigParser import ConfigParser + +try: + import readline # pylint: disable=W0611 +except ImportError: + pass + + +SERVER_MANUAL_HTTP = 'https://github.com/haiwen/seafile/wiki' + +class Utils(object): + '''Groups all helper functions here''' + @staticmethod + def welcome(): + '''Show welcome message''' + welcome_msg = '''\ +----------------------------------------------------------------- +This script will guide you to setup your seafile server using MySQL. +Make sure you have read seafile server manual at + + %s + +Press ENTER to continue +-----------------------------------------------------------------''' % SERVER_MANUAL_HTTP + print welcome_msg + raw_input() + + @staticmethod + def highlight(content): + '''Add ANSI color to content to get it highlighted on terminal''' + return '\x1b[33m%s\x1b[m' % content + + @staticmethod + def info(msg): + print msg + + @staticmethod + def error(msg): + '''Print error and exit''' + print + print 'Error: ' + msg + sys.exit(1) + + @staticmethod + def run_argv(argv, cwd=None, env=None, suppress_stdout=False, suppress_stderr=False): + '''Run a program and wait it to finish, and return its exit code. The + standard output of this program is supressed. + + ''' + with open(os.devnull, 'w') as devnull: + if suppress_stdout: + stdout = devnull + else: + stdout = sys.stdout + + if suppress_stderr: + stderr = devnull + else: + stderr = sys.stderr + + proc = subprocess.Popen(argv, + cwd=cwd, + stdout=stdout, + stderr=stderr, + env=env) + return proc.wait() + + @staticmethod + def run(cmdline, cwd=None, env=None, suppress_stdout=False, suppress_stderr=False): + '''Like run_argv but specify a command line string instead of argv''' + with open(os.devnull, 'w') as devnull: + if suppress_stdout: + stdout = devnull + else: + stdout = sys.stdout + + if suppress_stderr: + stderr = devnull + else: + stderr = sys.stderr + + proc = subprocess.Popen(cmdline, + cwd=cwd, + stdout=stdout, + stderr=stderr, + env=env, + shell=True) + return proc.wait() + + @staticmethod + def prepend_env_value(name, value, env=None, seperator=':'): + '''prepend a new value to a list''' + if env is None: + env = os.environ + + try: + current_value = env[name] + except KeyError: + current_value = '' + + new_value = value + if current_value: + new_value += seperator + current_value + + env[name] = new_value + + @staticmethod + def must_mkdir(path): + '''Create a directory, exit on failure''' + try: + os.mkdir(path) + except OSError, e: + Utils.error('failed to create directory %s:%s' % (path, e)) + + @staticmethod + def must_copy(src, dst): + '''Copy src to dst, exit on failure''' + try: + shutil.copy(src, dst) + except Exception, e: + Utils.error('failed to copy %s to %s: %s' % (src, dst, e)) + + @staticmethod + def find_in_path(prog): + if 'win32' in sys.platform: + sep = ';' + else: + sep = ':' + + dirs = os.environ['PATH'].split(sep) + for d in dirs: + d = d.strip() + if d == '': + continue + path = os.path.join(d, prog) + if os.path.exists(path): + return path + + return None + + @staticmethod + def get_python_executable(): + '''Return the python executable. This should be the PYTHON environment + variable which is set in setup-seafile-mysql.sh + + ''' + return os.environ['PYTHON'] + + @staticmethod + def read_config(fn): + '''Return a case sensitive ConfigParser by reading the file "fn"''' + cp = ConfigParser() + cp.optionxform = str + cp.read(fn) + + return cp + + @staticmethod + def write_config(cp, fn): + '''Return a case sensitive ConfigParser by reading the file "fn"''' + with open(fn, 'w') as fp: + cp.write(fp) + + @staticmethod + def ask_question(desc, + key=None, + note=None, + default=None, + validate=None, + yes_or_no=False, + password=False): + '''Ask a question, return the answer. + @desc description, e.g. "What is the port of ccnet?" + + @key a name to represent the target of the question, e.g. "port for + ccnet server" + + @note additional information for the question, e.g. "Must be a valid + port number" + + @default the default value of the question. If the default value is + not None, when the user enter nothing and press [ENTER], the default + value would be returned + + @validate a function that takes the user input as the only parameter + and validate it. It should return a validated value, or throws an + "InvalidAnswer" exception if the input is not valid. + + @yes_or_no If true, the user must answer "yes" or "no", and a boolean + value would be returned + + @password If true, the user input would not be echoed to the + console + + ''' + assert key or yes_or_no + # Format description + print + if note: + desc += '\n' + note + + desc += '\n' + if yes_or_no: + desc += '[ yes or no ]' + else: + if default: + desc += '[ default "%s" ]' % default + else: + desc += '[ %s ]' % key + + desc += ' ' + while True: + # prompt for user input + if password: + answer = getpass.getpass(desc).strip() + else: + answer = raw_input(desc).strip() + + # No user input: use default + if not answer: + if default: + answer = default + else: + continue + + # Have user input: validate answer + if yes_or_no: + if answer not in ['yes', 'no']: + print Utils.highlight('\nPlease answer yes or no\n') + continue + else: + return answer == 'yes' + else: + if validate: + try: + return validate(answer) + except InvalidAnswer, e: + print Utils.highlight('\n%s\n' % e) + continue + else: + return answer + + @staticmethod + def validate_port(port): + try: + port = int(port) + except ValueError: + raise InvalidAnswer('%s is not a valid port' % Utils.highlight(port)) + + if port <= 0 or port > 65535: + raise InvalidAnswer('%s is not a valid port' % Utils.highlight(port)) + + return port + + +class InvalidAnswer(Exception): + def __init__(self, msg): + Exception.__init__(self) + self.msg = msg + def __str__(self): + return self.msg + +### END of Utils +#################### + +class RPC(object): + def __init__(self): + import ccnet + ccnet_dir = os.environ['CCNET_CONF_DIR'] + self.rpc_client = ccnet.CcnetThreadedRpcClient(ccnet.ClientPool(ccnet_dir)) + + def get_db_email_users(self): + return self.rpc_client.get_emailusers('DB', 0, 1) + + def create_admin(self, email, user): + return self.rpc_client.add_emailuser(email, user, 1, 1) + +def need_create_admin(): + users = rpc.get_db_email_users() + return len(users) == 0 + +def create_admin(email, passwd): + if rpc.create_admin(email, passwd) < 0: + raise Exception('failed to create admin') + else: + print '\n\n' + print '----------------------------------------' + print 'Successfully created seafile admin' + print '----------------------------------------' + print '\n\n' + +def ask_admin_email(): + print + print '----------------------------------------' + print 'It\'s the first time you start the seafile server. Now let\'s create the admin account' + print '----------------------------------------' + def validate(email): + # whitespace is not allowed + if re.match(r'[\s]', email): + raise InvalidAnswer('%s is not a valid email address' % Utils.highlight(email)) + # must be a valid email address + if not re.match(r'^.+@.*\..+$', email): + raise InvalidAnswer('%s is not a valid email address' % Utils.highlight(email)) + + return email + + key = 'admin email' + question = 'What is the ' + Utils.highlight('email') + ' for the admin account?' + return Utils.ask_question(question, + key=key, + validate=validate) + +def ask_admin_password(): + def validate(password): + key = 'admin password again' + question = 'Enter the ' + Utils.highlight('password again:') + password_again = Utils.ask_question(question, + key=key, + password=True) + + if password_again != password: + raise InvalidAnswer('password mismatch') + + return password + + key = 'admin password' + question = 'What is the ' + Utils.highlight('password') + ' for the admin account?' + return Utils.ask_question(question, + key=key, + password=True, + validate=validate) + +rpc = RPC() + +def main(): + if not need_create_admin(): + return + + email = 'ADMIN_EMAIL' + passwd = 'ADMIN_PASSWORD' + + create_admin(email, passwd) + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + print '\n\n\n' + print Utils.highlight('Aborted.') + print + sys.exit(1) + except Exception, e: + print e + print Utils.highlight('Error happened during creating seafile admin.') + print diff --git a/sources/setup-seafile.sh b/sources/setup-seafile.sh index 3127373..6c6c7bb 100644 --- a/sources/setup-seafile.sh +++ b/sources/setup-seafile.sh @@ -228,7 +228,7 @@ fi seafile_data_dir=SEAFILE_DATA if [[ ${use_existing_seafile} != "true" ]]; then seafile_server_port=SEAFILE_PORT - fileserver_port=SEAHUB_PORT + fileserver_port=SEAFILE_FILESERVER_PORT fi sleep .5 @@ -357,49 +357,6 @@ function get_seahub_admin_passwd () { fi } -# get_seahub_admin_email; -# sleep .5; -# get_seahub_admin_passwd; -# seahub_admin_passwd_enc=$(echo -n ${seahub_admin_passwd} | sha1sum | grep -o "[0-9a-f]*") -# sleep .5; - -# printf "\n\n" -# echo "This is your seahub admin username/password" -# echo -# printf "admin username: \033[33m${seahub_admin_email}\033[m\n" -# printf "admin password: \033[33m**************\033[m\n\n" - -# echo -# echo "If you are OK with the configuration, press [ENTER] to continue." -# read dummy - -# usermgr_db_dir=${default_ccnet_conf_dir}/PeerMgr/ -# usermgr_db=${usermgr_db_dir}/usermgr.db - -# if [[ "${use_existing_ccnet}" != "true" ]]; then -# # create admin user/passwd entry in ccnet db -# if ! mkdir -p "${usermgr_db_dir}"; then -# echo "Failed to create seahub admin." -# err_and_quit; -# fi - -# sql="CREATE TABLE IF NOT EXISTS EmailUser (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, email TEXT, passwd TEXT, is_staff bool NOT NULL, is_active bool NOT NULL, ctime INTEGER)"; - -# if ! sqlite3 "${usermgr_db}" "${sql}" ; then -# rm -f "${usermgr_db}" -# echo "Failed to create seahub admin." -# err_and_quit; -# fi - -# sql="INSERT INTO EmailUser(email, passwd, is_staff, is_active, ctime) VALUES (\"${seahub_admin_email}\", \"${seahub_admin_passwd_enc}\", 1, 1, 0);" - -# if ! sqlite3 "${usermgr_db}" "${sql}" ; then -# rm -f "${usermgr_db}" -# echo "Failed to create seahub admin." -# err_and_quit; -# fi -# fi - echo "Creating seahub database now... " echo @@ -453,6 +410,7 @@ echo # ------------------------------------------- copy_user_manuals; + # ------------------------------------------- # final message # -------------------------------------------