Skip to content
Snippets Groups Projects
Commit cbd2a71a authored by Bob Mottram's avatar Bob Mottram
Browse files

New turtl app implementation

parent 18c9868c
No related branches found
No related tags found
No related merge requests found
#!/bin/bash
#
# _____ _ _
# | __|___ ___ ___ _| |___ _____| |_ ___ ___ ___
# | __| _| -_| -_| . | . | | . | . | | -_|
......@@ -6,15 +7,10 @@
#
# Freedom in the Cloud
#
# turtl app
#
# http://portallinux.es/instalacion-servidor-turtl-debian-8
# http://framacloud.org/cultiver-son-jardin/installation-de-turtl/
#
# License
# =======
#
# Copyright (C) 2016-2018 Bob Mottram <bob@freedombone.net>
# Copyright (C) 2018 Bob Mottram <bob@freedombone.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
......@@ -29,38 +25,34 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
VARIANTS="full full-vim writer"
VARIANTS='full full-vim'
IN_DEFAULT_INSTALL=0
INSTALLED_ON_DEFAULT_DOMAIN=0
SHOW_ON_ABOUT=1
NOT_ON_ARM=1
# whether to show the domain name in the web UI
SHOW_DOMAIN_IN_WEBADMIN=1
NOT_ON_API=0
TURTL_DOMAIN_NAME=
TURTL_CODE=
TURTL_ONION_PORT=8107
TURTL_PORT=8181
TURTL_REPO="https://github.com/turtl/api.git"
TURTL_COMMIT='53e00a5583f52de8f86ef380fe11c176b5738dcf'
TURTL_ADMIN_PASSWORD=
TURTL_STORAGE_LIMIT_MB=100
TURTL_BASE_DIR=/etc/turtl
# part of a hack to enable/disable signups
TURTL_SIGNUP_STRING='Signup a new user'
turtl_users_file=$TURTL_BASE_DIR/api/controllers/users.lisp
TURTL_SHORT_DESCRIPTION=$'Note taking'
TURTL_DESCRIPTION=$'Note taking'
TURTL_MOBILE_APP_URL=https://turtlapp.com/releases/mobile/turtl-android-0.6.4.apk
TURTL_ONION_PORT=9473
TURTL_REPO="https://github.com/turtl/server"
TURTL_COMMIT='475de66908c7537ddde4397e918f9da4ab2a5aea'
TURTL_PORT_INTERNAL=8181
TURTL_APP_VERSION='0.7.2'
# These parameters are used by the FreedomBox mobile app and web UI
TURTL_SHORT_DESCRIPTION='The secure collaborative notebook'
TURTL_DESCRIPTION='Whether its bookmarks or passwords, files or shopping lists...Turtl organizes it all and makes it easy to find later. Sync across your devices.'
TURTL_MOBILE_APP_URL="https://github.com/turtl/android/releases/download/v${TURTL_APP_VERSION}/turtl-${TURTL_APP_VERSION}-android.apk"
turtl_variables=(ONION_ONLY
DEFAULT_DOMAIN_NAME
TURTL_DOMAIN_NAME
TURTL_CODE
TURTL_STORAGE_LIMIT_MB
DDNS_PROVIDER
MY_EMAIL_ADDRESS
MY_USERNAME)
TURTL_DOMAIN_NAME
TURTL_CODE
DDNS_PROVIDER
MY_USERNAME)
function logging_on_turtl {
echo -n ''
......@@ -70,20 +62,17 @@ function logging_off_turtl {
echo -n ''
}
function change_password_turtl {
echo -n ''
# change_username="$1"
# new_user_password="$2"
}
function remove_user_turtl {
echo -n ''
# remove_username="$1"
remove_username="$1"
"${PROJECT_NAME}-pass" -u "$remove_username" --rmapp turtl
}
function add_user_turtl {
# new_username="$1"
# new_user_password="$2"
new_username="$1"
new_user_password="$2"
"${PROJECT_NAME}-pass" -u "$new_username" -a turtl -p "$new_user_password"
echo '0'
}
......@@ -92,113 +81,67 @@ function install_interactive_turtl {
ONION_ONLY='no'
fi
if [[ $ONION_ONLY != "no" ]]; then
TURTL_DOMAIN_NAME='notes.local'
if [[ "$ONION_ONLY" != "no" ]]; then
TURTL_DOMAIN_NAME='turtl.local'
write_config_param "TURTL_DOMAIN_NAME" "$TURTL_DOMAIN_NAME"
else
function_check interactive_site_details
interactive_site_details "turtl" "TURTL_DOMAIN_NAME" "TURTL_CODE"
fi
APP_INSTALLED=1
}
function turtl_disable_registrations {
if grep -q "$TURTL_SIGNUP_STRING" $turtl_users_file; then
if [ -f $turtl_users_file ]; then
cp $turtl_users_file $TURTL_BASE_DIR/.users.lisp
sed -i '/(route (:post "\/users") (req res)/,/(send-json res user))))/{//!d}' $turtl_users_file
sed -i 's|(send-json res user))))|())|g' $turtl_users_file
chown -R turtl:turtl $TURTL_BASE_DIR
systemctl restart turtl
fi
fi
function change_password_turtl {
curr_username="$1"
new_user_password="$2"
read_config_param 'TURTL_DOMAIN_NAME'
"${PROJECT_NAME}-pass" -u "$curr_username" -a turtl -p "$new_user_password"
}
function turtl_enable_registrations {
if ! grep -q "$TURTL_SIGNUP_STRING" $turtl_users_file; then
if [ -f $TURTL_BASE_DIR/.users.lisp ]; then
cp $TURTL_BASE_DIR/.users.lisp $turtl_users_file
rm $TURTL_BASE_DIR/.users.lisp
chown -R turtl:turtl $TURTL_BASE_DIR
systemctl restart turtl
function turtl_create_database {
if [ -f "$IMAGE_PASSWORD_FILE" ]; then
TURTL_ADMIN_PASSWORD="$(printf "%d" "$(cat "")")"
else
if [ ! "$TURTL_ADMIN_PASSWORD" ]; then
TURTL_ADMIN_PASSWORD=$(create_password "${MINIMUM_PASSWORD_LENGTH}")
fi
fi
}
if [ ! "$TURTL_ADMIN_PASSWORD" ]; then
return
fi
function configure_interactive_turtl_signups {
# This implements a hack which removes or adds the function needed
# to sign up new users. It should eventually be removed once that
# capability exists within the api
dialog --title $"Allow new turtl signups" \
--backtitle $"Freedombone Control Panel" \
--defaultno \
--yesno $"\\nAllow registration of new users?" 10 60
sel=$?
case $sel in
0)
turtl_enable_registrations
dialog --title $"Allow new turtl signups" \
--msgbox $"New turtl user registrations are now allowed" 6 60
return;;
1)
turtl_disable_registrations
dialog --title $"Disable new turtl signups" \
--msgbox $"New turtl user registrations are now disabled" 6 60
return;;
255) return;;
esac
systemctl restart postgresql
run_system_query_postgresql "CREATE USER turtl WITH PASSWORD '$TURTL_ADMIN_PASSWORD';"
run_system_query_postgresql "CREATE DATABASE turtl OWNER turtl;"
run_system_query_postgresql "GRANT ALL PRIVILEGES ON DATABASE turtl to turtl;"
run_system_query_postgresql "set statement_timeout to 40000;"
}
function configure_interactive_turtl_storage {
data=$(mktemp 2>/dev/null)
dialog --title $"Change storage limit" \
--backtitle $"Freedombone Control Panel" \
--inputbox $"Enter a storage limit in megabytes." 8 75 "$TURTL_STORAGE_LIMIT_MB" 2>"$data"
sel=$?
case $sel in
0)
STORAGE=$(<"$data")
if [ ${#STORAGE} -gt 0 ]; then
TURTL_STORAGE_LIMIT_MB=$STORAGE
sed -i "s|defparameter *default-storage-limit*.*|defparameter *default-storage-limit* ${TURTL_STORAGE_LIMIT_MB})|g" $TURTL_BASE_DIR/api/config/config.lisp
systemctl restart turtl
dialog --title $"Change storage limit" \
--msgbox $"Storage limit changed to ${TURTL_STORAGE_LIMIT_MB}M" 6 50
fi
;;
esac
rm -f "$data"
function reconfigure_turtl {
# This is used if you need to switch identity. Dump old keys and generate new ones
echo -n ''
}
function configure_interactive_turtl {
data=$(mktemp 2>/dev/null)
dialog --backtitle $"Freedombone Control Panel" \
--title $"turtl app settings" \
--radiolist $"Choose an operation:" 12 70 3 \
1 $"Enable/disable new user registrations" off \
2 $"Change storage limit" off \
3 $"Exit" on 2> "$data"
sel=$?
case $sel in
1) rm -f "$data"
exit 1;;
255) rm -f "$data"
exit 1;;
esac
case $(cat "$data") in
1) configure_interactive_turtl_signups;;
2) configure_interactive_turtl_storage;;
3) rm -f "$data"
return;;
esac
rm -f "$data"
}
W=(1 $"Option 1"
2 $"Option 2")
function reconfigure_turtl {
if [ -d $TURTL_BASE_DIR/data ]; then
rm -rf $TURTL_BASE_DIR/data/*
fi
while true
do
# shellcheck disable=SC2068
selection=$(dialog --backtitle $"Freedombone Administrator Control Panel" --title $"turtl" --menu $"Choose an operation, or ESC for main menu:" 14 70 3 "${W[@]}" 3>&2 2>&1 1>&3)
if [ ! "$selection" ]; then
break
fi
case $selection in
1) # call some function for option 1
;;
2) # call some function for option 2
;;
esac
done
}
function upgrade_turtl {
......@@ -207,88 +150,76 @@ function upgrade_turtl {
return
fi
read_config_param "TURTL_DOMAIN_NAME"
function_check set_repo_commit
set_repo_commit $TURTL_BASE_DIR/api "turtl commit" "$TURTL_COMMIT" $TURTL_REPO
# this is used as a crude way of disabling signups and so
# should be superceded in future
if [ -f $TURTL_BASE_DIR/.users.lisp ]; then
turtl_disable_registrations
if grep -q "turtl domain" "$COMPLETION_FILE"; then
TURTL_DOMAIN_NAME=$(get_completion_param "turtl domain")
fi
systemctl restart turtl
nginx_dissite $TURTL_DOMAIN_NAME
chown -R turtl:turtl $TURTL_BASE_DIR
nginx_ensite $TURTL_DOMAIN_NAME
# update to the next commit
set_repo_commit "/etc/turtl" "turtl commit" "$TURTL_COMMIT" "$TURTL_REPO"
chown -R turtl:turtl "/etc/turtl"
systemctl restart turtl
}
function backup_local_turtl {
read_config_param "TURTL_DOMAIN_NAME"
source_directory=$TURTL_BASE_DIR
if [ -d $source_directory ]; then
dest_directory=turtl
function_check suspend_site
suspend_site ${TURTL_DOMAIN_NAME}
function_check backup_directory_to_usb
backup_directory_to_usb $source_directory $dest_directory
function_check restart_site
restart_site
TURTL_DOMAIN_NAME='turtl'
if grep -q "turtl domain" "$COMPLETION_FILE"; then
TURTL_DOMAIN_NAME=$(get_completion_param "turtl domain")
fi
source_directory=/var/lib/rethinkdb
if [ -d $source_directory ]; then
dest_directory=rethinkdb
function_check suspend_site
suspend_site ${TURTL_DOMAIN_NAME}
function_check backup_directory_to_usb
backup_directory_to_usb $source_directory $dest_directory
source_directory=/etc/turtl
function_check restart_site
restart_site
fi
suspend_site "${TURTL_DOMAIN_NAME}"
systemctl stop turtl
dest_directory=turtl
backup_directory_to_usb "$source_directory" $dest_directory
USE_POSTGRESQL=1
backup_database_to_usb turtl
restart_site
systemctl start turtl
}
function restore_local_turtl {
read_config_param "TURTL_DOMAIN_NAME"
if [ $TURTL_DOMAIN_NAME ]; then
temp_restore_dir=/root/tempturtl
restore_directory_from_usb $temp_restore_dir turtl
if ! grep -q "turtl domain" "$COMPLETION_FILE"; then
return
fi
TURTL_DOMAIN_NAME=$(get_completion_param "turtl domain")
if [ ! "$TURTL_DOMAIN_NAME" ]; then
return
fi
suspend_site "${TURTL_DOMAIN_NAME}"
systemctl stop turtl
if [ -d ${temp_restore_dir}/etc/turtl ]; then
cp -r ${temp_restore_dir}/etc/turtl/* /etc/turtl/
else
cp -r ${temp_restore_dir}/* /etc/turtl/
fi
# shellcheck disable=SC2181
if [ ! "$?" = "0" ]; then
set_user_permissions
backup_unmount_drive
exit 36723
fi
rm -rf ${temp_restore_dir}
chown -R turtl:turtl $TURTL_BASE_DIR
temp_restore_dir=/root/tempturtl
turtl_dir=/etc/turtl
temp_restore_dir=/root/temprethinkdb
restore_directory_from_usb $temp_restore_dir rethinkdb
turtl_create_database
if [ -d ${temp_restore_dir}/var/lib/rethinkdb ]; then
cp -r ${temp_restore_dir}/var/lib/rethinkdb/* /var/lib/rethinkdb/
else
cp -r ${temp_restore_dir}/* /var/lib/rethinkdb/
fi
USE_POSTGRESQL=1
restore_database turtl
if [ -d $temp_restore_dir ]; then
rm -rf $temp_restore_dir
fi
# shellcheck disable=SC2181
if [ ! "$?" = "0" ]; then
set_user_permissions
backup_unmount_drive
exit 378324
restore_directory_from_usb $temp_restore_dir turtl
if [ -d $temp_restore_dir ]; then
if [ -d "$temp_restore_dir$turtl_dir" ]; then
cp -rp "$temp_restore_dir$turtl_dir"/* "$turtl_dir"/
else
if [ ! -d "$turtl_dir" ]; then
mkdir "$turtl_dir"
fi
cp -rp "$temp_restore_dir"/* "$turtl_dir"/
fi
rm -rf ${temp_restore_dir}
chown -R turtl:turtl "$turtl_dir"
rm -rf $temp_restore_dir
fi
systemctl start turtl
restart_site
}
function backup_remote_turtl {
......@@ -300,383 +231,197 @@ function restore_remote_turtl {
}
function remove_turtl {
if [ ! -d $TURTL_BASE_DIR ]; then
return
fi
systemctl stop turtl
systemctl disable turtl
rm /etc/systemd/system/turtl.service
systemctl daemon-reload
nginx_dissite "$TURTL_DOMAIN_NAME"
remove_certs "$TURTL_DOMAIN_NAME"
remove_rethinkdb
remove_app turtl
remove_completion_param install_turtl
sed -i '/turtl/d' "$COMPLETION_FILE"
nginx_dissite $TURTL_DOMAIN_NAME
if [ -f /etc/nginx/sites-available/$TURTL_DOMAIN_NAME ]; then
rm /etc/nginx/sites-available/$TURTL_DOMAIN_NAME
if [ -f /etc/systemd/system/turtl.service ]; then
systemctl stop turtl
systemctl disable turtl
rm /etc/systemd/system/turtl.service
fi
remove_certs $TURTL_DOMAIN_NAME
function_check remove_onion_service
remove_onion_service turtl ${TURTL_ONION_PORT}
function_check remove_ddns_domain
remove_ddns_domain $TURTL_DOMAIN_NAME
rm -rf /etc/rethinkdb
rm -rf /var/lib/rethinkdb
rm -rf $TURTL_BASE_DIR
groupdel -f turtl
userdel -r turtl
}
remove_nodejs turtl
function turtl_setup {
PIDFILE=${PIDFILE:-nil}
BINDADDR=${BINDADDR:-0.0.0.0}
BINDPORT=${BINDPORT:-8181}
PROD_ERR_HANDLING=${PROD_ERR_HANDLING:-t}
if [[ $ONION_ONLY == 'no' ]]; then
FQDN=${FQDN:-$TURTL_DOMAIN_NAME}
SITE_URL=${SITE_URL:-https://$TURTL_DOMAIN_NAME}
else
FQDN=${FQDN:-$TURTL_ONION_HOSTNAME}
SITE_URL=${SITE_URL:-http://$TURTL_ONION_HOSTNAME}
fi
ADMIN_EMAIL=${ADMIN_EMAIL:-$MY_EMAIL_ADDRESS}
EMAIL_FROM=${EMAIL_FROM:-noreply@$DEFAULT_DOMAIN_NAME}
SMTP_USER=${SMTP_USER:-}
SMTP_PASS=${SMTP_PASS:-}
DISPLAY_ERRORS=${DISPLAY_ERRORS:-t}
DEFAULT_STORAGE_LIMIT=${DEFAULT_STORAGE_LIMIT:-100}
STORAGE_INVITE_CREDIT=${STORAGE_INVITE_CREDIT:-25}
if [[ $ONION_ONLY == 'no' ]]; then
LOCAL_UPLOAD_URL=${LOCAL_UPLOAD_URL:-https://$TURTL_DOMAIN_NAME}
else
LOCAL_UPLOAD_URL=${LOCAL_UPLOAD_URL:-http://$TURTL_ONION_HOSTNAME}
if [ -d "/var/www/$TURTL_DOMAIN_NAME" ]; then
rm -rf "/var/www/$TURTL_DOMAIN_NAME"
fi
LOCAL_UPLOAD_PATH=${LOCAL_UPLOAD_PATH:-"$TURTL_BASE_DIR/data"}
AWS_S3_TOKEN=${AWS_S3_TOKEN:-(:token ''
:secret ''
:bucket ''
:endpoint 'https://s3.amazonaws.com')}
# generates the config-file
cat << __ENDCONFIG__ > $TURTL_BASE_DIR/api/config/config.lisp
(in-package :turtl)
(defparameter *root* (asdf:system-relative-pathname :turtl #P""))
(defparameter *pid-file* "${PIDFILE}")
(defvar *server-bind* "${BINDADDR}")
(defvar *server-port* ${BINDPORT})
(defvar *db-name* "turtl")
(defvar *db-host* "127.0.0.1")
(defvar *db-port* 28015)
(defvar *production-error-handling* ${PROD_ERR_HANDLING})
(defvar *enable-hsts-header* nil)
(defvar *site-url* "${SITE_URL}")
(defvar *api-path* "")
(defvar *admin-email* "${ADMIN_EMAIL}")
(defvar *email-from* "${EMAIL_FROM}")
(defvar *email-user* "${SMTP_USER}")
(defvar *email-pass* "${SMTP_PASS}")
(defvar *display-errors* ${DISPLAY_ERRORS})
(defparameter *default-storage-limit* ${DEFAULT_STORAGE_LIMIT})
(defparameter *storage-invite-credit* ${STORAGE_INVITE_CREDIT})
(vom:config :turtl :info)
(defvar *local-upload* "${LOCAL_UPLOAD_PATH}")
(defvar *local-upload-url* "${LOCAL_UPLOAD_URL}")
(defvar *amazon-s3* "${AWS_S3_TOKEN}")
__ENDCONFIG__
cat $TURTL_BASE_DIR/api/config/config.footer >> $TURTL_BASE_DIR/api/config/config.lisp
# start the turtl server
systemctl restart rethinkdb
if [ ! -f $TURTL_BASE_DIR/quicklisp/setup.lisp ]; then
echo $"$TURTL_BASE_DIR/quicklisp/setup.lisp was not found"
exit 6238234
if [ -f "/etc/nginx/sites-available/$TURTL_DOMAIN_NAME" ]; then
rm "/etc/nginx/sites-available/$TURTL_DOMAIN_NAME"
fi
{ echo '[Unit]';
echo 'Description=Note taking service';
echo 'Documentation=http://turtl.it';
echo 'Requires=network.target';
echo 'Requires=rethinkdb.service';
echo 'After=network.target';
echo 'After=rethinkdb.service';
echo '';
echo '[Service]';
echo 'Type=simple';
echo 'User=turtl';
echo "WorkingDirectory=$TURTL_BASE_DIR/api/"; } > /etc/systemd/system/turtl.service
if [[ "$check_architecture" == *"64"* && "$check_architecture" != *"arm"* ]]; then
echo "ExecStart=$TURTL_BASE_DIR/ccl/lx86cl64 -l $TURTL_BASE_DIR/quicklisp/setup.lisp -l launch.lisp" >> /etc/systemd/system/turtl.service
else
if [[ "$check_architecture" != *"arm"* ]]; then
echo "ExecStart=$TURTL_BASE_DIR/ccl/lx86cl -l $TURTL_BASE_DIR/quicklisp/setup.lisp -l launch.lisp" >> /etc/systemd/system/turtl.service
else
echo "ExecStart=$TURTL_BASE_DIR/ccl/armcl -l $TURTL_BASE_DIR/quicklisp/setup.lisp -l launch.lisp" >> /etc/systemd/system/turtl.service
fi
drop_database_postgresql turtl
remove_onion_service turtl "${TURTL_ONION_PORT}"
if grep -q "turtl" /etc/crontab; then
sed -i "/turtl/d" /etc/crontab
fi
{ echo '';
echo '[Install]';
echo 'WantedBy=multi-user.target'; } >> /etc/systemd/system/turtl.service
chmod +x /etc/systemd/system/turtl.service
remove_app turtl
remove_completion_param install_turtl
sed -i '/turtl/d' "$COMPLETION_FILE"
chown -R turtl:turtl $TURTL_BASE_DIR
systemctl enable turtl
systemctl daemon-reload
systemctl start turtl
remove_ddns_domain "$TURTL_DOMAIN_NAME"
}
function install_turtl_api {
# https://github.com/ArthurGarnier/turtl-docker
$INSTALL_PACKAGES wget libterm-readline-perl-perl gcc libuv1-dev
function install_turtl {
install_postgresql
if [ ! -d $TURTL_BASE_DIR ]; then
mkdir -p $TURTL_BASE_DIR
fi
cd "$TURTL_BASE_DIR" || exit 745726542
mkdir cd $TURTL_BASE_DIR/data
check_architecture=$(uname -a)
# Install ccl
if [[ "$check_architecture" != *"arm"* ]]; then
wget -P $TURTL_BASE_DIR/ ftp://ftp.clozure.com/pub/release/1.11/ccl-1.11-linuxx86.tar.gz
mkdir -p $TURTL_BASE_DIR/ccl
tar xvzf $TURTL_BASE_DIR/ccl-1.11-linuxx86.tar.gz -C $TURTL_BASE_DIR/ccl --strip-components=1
else
wget -P $TURTL_BASE_DIR/ ftp://ftp.clozure.com/pub/release/1.11/ccl-1.11-linuxarm.tar.gz
mkdir -p $TURTL_BASE_DIR/ccl
tar xvzf $TURTL_BASE_DIR/ccl-1.11-linuxarm.tar.gz -C $TURTL_BASE_DIR/ccl --strip-components=1
install_nodejs turtl
if [ ! "$TURTL_DOMAIN_NAME" ]; then
echo $'No domain name was given'
exit 3568356
fi
# install quicklisp
cat << __ENDCONFIG__ > $TURTL_BASE_DIR/quicklisp_install
(load (compile-file "asdf.lisp"))
(load (compile-file "quicklisp.lisp"))
(quicklisp-quickstart:install)
(ql:system-apropos "vecto")
(ql:quickload "alexandria")
(ql:quickload "babel")
(ql:quickload "blackbird")
(ql:quickload "bordeaux-threads")
(ql:quickload "cffi")
(ql:quickload "chipz")
(ql:quickload "chunga")
(ql:quickload "cl-annot")
(ql:quickload "cl-async")
(ql:quickload "cl-async-future")
(ql:quickload "cl-base64")
(ql:quickload "cl-fad")
(ql:quickload "cl-libuv")
(ql:quickload "cl-mongo-id")
(ql:quickload "cl-ppcre")
(ql:quickload "cl-rethinkdb")
(ql:quickload "cl-smtp")
(ql:quickload "cl+ssl")
(ql:quickload "cl-syntax")
(ql:quickload "cl-utilities")
(ql:quickload "cl-vectors")
(ql:quickload "do-urlencode")
(ql:quickload "drakma")
(ql:quickload "drakma-async")
(ql:quickload "event-glue")
(ql:quickload "fast-http")
(ql:quickload "fast-io")
(ql:quickload "flexi-streams")
(ql:quickload "ironclad")
(ql:quickload "jonathan")
(ql:quickload "local-time")
(ql:quickload "md5")
(ql:quickload "named-readtables")
(ql:quickload "nibbles")
(ql:quickload "proc-parse")
(ql:quickload "puri")
(ql:quickload "quri")
(ql:quickload "salza2")
(ql:quickload "secure-random")
(ql:quickload "smart-buffer")
(ql:quickload "split-sequence")
(ql:quickload "static-vectors")
(ql:quickload "trivial-backtrace")
(ql:quickload "trivial-features")
(ql:quickload "trivial-garbage")
(ql:quickload "trivial-gray-streams")
(ql:quickload "trivial-types")
(ql:quickload "usocket")
(ql:quickload "vecto")
(ql:quickload "vom")
(ql:quickload "wookie")
(ql:quickload "xmls")
(ql:quickload "xsubseq")
(ql:quickload "yason")
(ql:quickload "zpb-ttf")
(ql:quickload "zpng")
(ql:add-to-init-file)
(ccl::quit)
__ENDCONFIG__
if [ ! -f asdf.lisp ]; then
wget https://common-lisp.net/project/asdf/asdf.lisp
if [ -d "/var/www/$TURTL_DOMAIN_NAME/htdocs" ]; then
rm -rf "/var/www/$TURTL_DOMAIN_NAME/htdocs"
fi
if [ ! -f quicklisp.lisp ]; then
wget https://beta.quicklisp.org/quicklisp.lisp
mkdir "/var/www/$TURTL_DOMAIN_NAME"
if [ -d /repos/turtl ]; then
mkdir -p "/var/www/$TURTL_DOMAIN_NAME/htdocs"
cp -r -p /repos/turtl/. "/etc/turtl"
cd "/etc/turtl" || exit 36487365
git pull
else
mkdir "/var/www/$TURTL_DOMAIN_NAME/htdocs"
git_clone "$TURTL_REPO" "/etc/turtl"
fi
if [ -d $TURTL_BASE_DIR ]; then
chown -R turtl:turtl $TURTL_BASE_DIR
fi
adduser --disabled-login --home=$TURTL_BASE_DIR --gecos 'turtl' turtl
if [ ! -d $TURTL_BASE_DIR ]; then
echo $"$TURTL_BASE_DIR directory not created"
exit 263493
if [ ! -d "/etc/turtl" ]; then
echo $'Unable to clone turtl repo'
exit 87525
fi
groupadd turtl
chown -R turtl:turtl $TURTL_BASE_DIR
cd "/etc/turtl" || exit 3463754637
git checkout "$TURTL_COMMIT" -b "$TURTL_COMMIT"
set_completion_param "turtl commit" "$TURTL_COMMIT"
if [[ "$check_architecture" != *"arm"* ]]; then
if [[ "$check_architecture" == *"64"* ]]; then
su -c "cat $TURTL_BASE_DIR/quicklisp_install | $TURTL_BASE_DIR/ccl/lx86cl64" - turtl
else
su -c "cat $TURTL_BASE_DIR/quicklisp_install | $TURTL_BASE_DIR/ccl/lx86cl" - turtl
fi
else
su -c "cat $TURTL_BASE_DIR/quicklisp_install | $TURTL_BASE_DIR/ccl/larmcl" - turtl
if ! npm install; then
echo $'Failed to install turtl'
exit 24682468
fi
rm $TURTL_BASE_DIR/quicklisp_install
install_rethinkdb
echo "http-port=8091" > /etc/rethinkdb/instances.d/turtl.conf
chown -R rethinkdb:rethinkdb /var/lib/rethinkdb
mkdir /etc/turtl/plugins || exit 35683
./scripts/init-db.sh
# install turtl API
cd "$TURTL_BASE_DIR/" || exit 6428462
chmod g+w "/var/www/$TURTL_DOMAIN_NAME/htdocs"
chown -R www-data:www-data "/var/www/$TURTL_DOMAIN_NAME/htdocs"
if [ -d /repos/turtl ]; then
mkdir -p $TURTL_BASE_DIR/api
cp -r -p /repos/turtl/. $TURTL_BASE_DIR/api
cd "$TURTL_BASE_DIR/api" || exit 57141845
git pull
else
git clone $TURTL_REPO $TURTL_BASE_DIR/api
fi
turtl_create_database
cd "$TURTL_BASE_DIR/api" || exit 35814614
git checkout $TURTL_COMMIT -b $TURTL_COMMIT
set_completion_param "turtl commit" "$TURTL_COMMIT"
cd "$TURTL_BASE_DIR/quicklisp/local-projects" || exit 43618941415
git clone git://github.com/orthecreedence/cl-hash-util
if [[ "$check_architecture" != *"arm"* ]]; then
if [[ "$check_architecture" == *"64"* ]]; then
su -c "cat '(ccl:quit)' | $TURTL_BASE_DIR/ccl/lx86cl64 -l $TURTL_BASE_DIR/quicklisp/setup.lisp" - turtl
else
su -c "cat '(ccl:quit)' | $TURTL_BASE_DIR/ccl/lx86cl -l $TURTL_BASE_DIR/quicklisp/setup.lisp" - turtl
fi
add_ddns_domain "$TURTL_DOMAIN_NAME"
TURTL_ONION_HOSTNAME=$(add_onion_service turtl 80 "${TURTL_ONION_PORT}")
cp /etc/turtl/config/config.yaml.default /etc/turtl/config/config.yaml
sed -i "s|connstr:.*|connstr: 'postgres://turtl:${TURTL_ADMIN_PASSWORD}@127.0.0.1:5432/turtl'|g" /etc/turtl/config/config.yaml
if [[ "$ONION_ONLY" != 'no' ]]; then
sed -i "s|api_url:.*|api_url: 'https://${TURTL_DOMAIN_NAME}'|g" /etc/turtl/config/config.yaml
sed -i "s|www_url:.*|www_url: 'https://${TURTL_DOMAIN_NAME}/web'|g" /etc/turtl/config/config.yaml
else
su -c "cat '(ccl:quit)' | $TURTL_BASE_DIR/ccl/larmcl -l $TURTL_BASE_DIR/quicklisp/setup.lisp" - turtl
sed -i "s|api_url:.*|api_url: 'http://${TURTL_ONION_HOSTNAME}'|g" /etc/turtl/config/config.yaml
sed -i "s|www_url:.*|www_url: 'http://${TURTL_ONION_HOSTNAME}/web'|g" /etc/turtl/config/config.yaml
fi
sed -i "s|admin:.*|admin: '${MY_EMAIL_ADDRESS}'|g" /etc/turtl/config/config.yaml
sed -i "s|info:.*|info: 'Turtl <${MY_EMAIL_ADDRESS}>'|g" /etc/turtl/config/config.yaml
sed -i "s|invites:.*|invites: '${MY_EMAIL_ADDRESS}'|g" /etc/turtl/config/config.yaml
TURTL_HASH="$(create_random_string 30)$(create_random_string 30)$(create_random_string 30)$(create_random_string 30)$(create_random_string 30)$(create_random_string 30)"
sed -i "s|secure_hash_salt:.*|secure_hash_salt: \"${TURTL_HASH}\"|g" /etc/turtl/config/config.yaml
if [ ! -d /etc/turtl/public/uploads ]; then
mkdir -p /etc/turtl/public/uploads
fi
sed -i "s|local:.*|local: '/etc/turtl/public/uploads'|g" /etc/turtl/config/config.yaml
# config
{ echo '(defvar *enabled-cors-resources* "resource://turtl-at-lyonbros-dot-com"';
echo ' "When set, will enable CORS for resource:// origins if they match the given';
echo ' string. Entries should be comma separated (this string is passed verbatim in';
echo ' the Access-Control-Allow-Origin header).")';
echo '(defparameter *public-actions*';
echo " \`((:post . ,(concatenate 'string *api-path* \"/users\"))";
echo " (:post . ,(concatenate 'string *api-path* \"/log/error\"))";
echo ' (:post . "/cla/sign")';
echo ' (:get . "/ping")';
echo ' (:get . "/admin")';
echo " (:get . ,(cl-ppcre:create-scanner (concatenate 'string *api-path* \"/invites/codes/([0-9a-f-]+)\"))))";
echo " \"A list of public resources/actions that do not require authentication.\")";
echo "(defvar *analytics* '(:enabled t";
echo ' :db "analytics"))'; } > "$TURTL_BASE_DIR/api/config/config.footer"
cp $TURTL_BASE_DIR/asdf.lisp $TURTL_BASE_DIR/api
echo '(load (compile-file "asdf.lisp"))' > $TURTL_BASE_DIR/api/launch.lisp
echo "(pushnew \"./\" asdf:*central-registry* :test #'equal)" >> $TURTL_BASE_DIR/api/launch.lisp
echo '(load "start")' >> $TURTL_BASE_DIR/api/launch.lisp
TURTL_ONION_HOSTNAME=$(add_onion_service turtl 80 ${TURTL_ONION_PORT})
turtl_setup
}
function install_turtl_nginx {
turtl_nginx_site=/etc/nginx/sites-available/$TURTL_DOMAIN_NAME
if [[ $ONION_ONLY == "no" ]]; then
function_check nginx_http_redirect
nginx_http_redirect $TURTL_DOMAIN_NAME
if [[ "$ONION_ONLY" == "no" ]]; then
nginx_http_redirect "$TURTL_DOMAIN_NAME" "index index.html"
{ echo 'server {';
echo ' listen 443 ssl;';
echo ' #listen [::]:443 ssl;';
echo " server_name ${TURTL_DOMAIN_NAME};";
echo '';
echo ' # Security'; } >> "$turtl_nginx_site"
function_check nginx_ssl
nginx_ssl $TURTL_DOMAIN_NAME
echo " server_name $TURTL_DOMAIN_NAME;";
echo ''; } >> "$turtl_nginx_site"
nginx_compress "$TURTL_DOMAIN_NAME"
echo '' >> "$turtl_nginx_site"
echo ' # Security' >> "$turtl_nginx_site"
nginx_ssl "$TURTL_DOMAIN_NAME"
function_check nginx_security_options
nginx_security_options $TURTL_DOMAIN_NAME
nginx_security_options "$TURTL_DOMAIN_NAME"
{ echo ' add_header Strict-Transport-Security max-age=15768000;';
echo '';
echo ' # Logs';
echo ' access_log /dev/null;';
echo ' error_log /dev/null;';
echo ' access_log /dev/null;';
echo ' error_log /dev/null;';
echo '';
echo " root /var/www/$TURTL_DOMAIN_NAME/htdocs;";
echo '';
echo ' index index.html;';
echo ' # Location';
echo ' location / {'; } >> "$turtl_nginx_site"
function_check nginx_limits
nginx_limits $TURTL_DOMAIN_NAME '15m'
{ echo " proxy_pass http://localhost:${TURTL_PORT}/;";
echo " proxy_set_header Host \$host;";
echo ' proxy_buffering off;';
nginx_limits "$TURTL_DOMAIN_NAME" '15m'
{ echo " proxy_pass http://localhost:$TURTL_PORT_INTERNAL;";
echo ' }';
echo '';
echo ' location ^~ /web {';
echo ' }';
echo '}'; } >> "$turtl_nginx_site"
else
echo -n '' > $turtl_nginx_site
echo -n '' > "$turtl_nginx_site"
fi
{ echo 'server {';
echo " listen 127.0.0.1:${TURTL_ONION_PORT};";
echo ' port_in_redirect off;';
echo " server_name ${TURTL_ONION_HOSTNAME};";
echo ''; } >> $turtl_nginx_site
function_check nginx_security_options
nginx_security_options $TURTL_DOMAIN_NAME
echo " listen 127.0.0.1:$TURTL_ONION_PORT default_server;";
echo " server_name $TURTL_ONION_HOSTNAME;";
echo ''; } >> "$turtl_nginx_site"
nginx_compress "$TURTL_DOMAIN_NAME"
echo '' >> "$turtl_nginx_site"
nginx_security_options "$TURTL_DOMAIN_NAME"
{ echo '';
echo ' # Logs';
echo ' access_log /dev/null;';
echo ' error_log /dev/null;';
echo ' access_log /dev/null;';
echo ' error_log /dev/null;';
echo '';
echo " root /var/www/$TURTL_DOMAIN_NAME/htdocs;";
echo '';
echo ' index index.html;';
echo ' # Location';
echo ' location / {'; } >> "$turtl_nginx_site"
nginx_limits "$TURTL_DOMAIN_NAME" '15m'
{ echo " proxy_pass http://localhost:$TURTL_PORT_INTERNAL;";
echo ' }';
echo '';
echo ' location / {'; } >> $turtl_nginx_site
function_check nginx_limits
nginx_limits $TURTL_DOMAIN_NAME '15m'
{ echo " proxy_pass http://localhost:${TURTL_PORT}/;";
echo " proxy_set_header Host \$host;";
echo ' proxy_buffering off;';
echo ' location ^~ /web {';
echo ' }';
echo '}'; } >> $turtl_nginx_site
echo '}'; } >> "$turtl_nginx_site"
function_check add_ddns_domain
add_ddns_domain $TURTL_DOMAIN_NAME
adduser --system --home="/etc/turtl" --group turtl
set_completion_param "turtl domain" "$TURTL_DOMAIN_NAME"
{ echo '[Unit]';
echo 'Description=turtl';
echo 'After=syslog.target';
echo 'After=network.target';
echo "Documentation=$TURTL_REPO";
echo '';
echo '[Service]';
echo 'Type=simple';
echo 'User=turtl';
echo 'Group=turtl';
echo 'WorkingDirectory=/etc/turtl';
echo 'ExecStart=/usr/local/bin/npm server.js';
echo 'Environment=USER=turtl';
echo 'Restart=always';
echo 'StandardError=syslog';
echo '';
echo '[Install]';
echo 'WantedBy=multi-user.target'; } > "/etc/systemd/system/turtl.service"
systemctl enable turtl
chown -R turtl:turtl "/etc/turtl"
systemctl start turtl
function_check create_site_certificate
create_site_certificate $TURTL_DOMAIN_NAME 'yes'
create_site_certificate "$TURTL_DOMAIN_NAME" 'yes'
function_check nginx_ensite
nginx_ensite $TURTL_DOMAIN_NAME
nginx_ensite "$TURTL_DOMAIN_NAME"
systemctl restart nginx
}
function install_turtl {
install_turtl_api
install_turtl_nginx
"${PROJECT_NAME}-pass" -u "$MY_USERNAME" -a turtl -p "$TURTL_ADMIN_PASSWORD"
set_completion_param "turtl domain" "$TURTL_DOMAIN_NAME"
APP_INSTALLED=1
}
# NOTE: deliberately there is no "exit 0"
......@@ -375,7 +375,7 @@ if [[ "$database_type" == "mariadb" || "$database_type" == "mysql" || "$database
fi
if [[ "$database_type" == "postgres"* ]]; then
echo ' systemctl restart postgresql'
echo " run_system_query_postgresql \"CREATE USER peertube WITH PASSWORD '\$${app_name_upper}_ADMIN_PASSWORD';\""
echo " run_system_query_postgresql \"CREATE USER ${app_name} WITH PASSWORD '\$${app_name_upper}_ADMIN_PASSWORD';\""
echo " run_system_query_postgresql \"CREATE DATABASE ${app_name} OWNER ${app_name};\""
echo " run_system_query_postgresql \"GRANT ALL PRIVILEGES ON DATABASE ${app_name} to ${app_name};\""
echo " run_system_query_postgresql \"set statement_timeout to 40000;\""
......
#!/bin/bash
# _____ _ _
# | __|___ ___ ___ _| |___ _____| |_ ___ ___ ___
# | __| _| -_| -_| . | . | | . | . | | -_|
# |__| |_| |___|___|___|___|_|_|_|___|___|_|_|___|
#
# Freedom in the Cloud
#
# turtl app
#
# http://portallinux.es/instalacion-servidor-turtl-debian-8
# http://framacloud.org/cultiver-son-jardin/installation-de-turtl/
#
# License
# =======
#
# Copyright (C) 2016-2018 Bob Mottram <bob@freedombone.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
VARIANTS="full full-vim writer"
IN_DEFAULT_INSTALL=0
SHOW_ON_ABOUT=1
NOT_ON_ARM=1
TURTL_DOMAIN_NAME=
TURTL_CODE=
TURTL_ONION_PORT=8107
TURTL_PORT=8181
TURTL_REPO="https://github.com/turtl/api.git"
TURTL_COMMIT='53e00a5583f52de8f86ef380fe11c176b5738dcf'
TURTL_ADMIN_PASSWORD=
TURTL_STORAGE_LIMIT_MB=100
TURTL_BASE_DIR=/etc/turtl
# part of a hack to enable/disable signups
TURTL_SIGNUP_STRING='Signup a new user'
turtl_users_file=$TURTL_BASE_DIR/api/controllers/users.lisp
TURTL_SHORT_DESCRIPTION=$'Note taking'
TURTL_DESCRIPTION=$'Note taking'
TURTL_MOBILE_APP_URL=https://turtlapp.com/releases/mobile/turtl-android-0.6.4.apk
turtl_variables=(ONION_ONLY
DEFAULT_DOMAIN_NAME
TURTL_DOMAIN_NAME
TURTL_CODE
TURTL_STORAGE_LIMIT_MB
DDNS_PROVIDER
MY_EMAIL_ADDRESS
MY_USERNAME)
function logging_on_turtl {
echo -n ''
}
function logging_off_turtl {
echo -n ''
}
function change_password_turtl {
echo -n ''
# change_username="$1"
# new_user_password="$2"
}
function remove_user_turtl {
echo -n ''
# remove_username="$1"
}
function add_user_turtl {
# new_username="$1"
# new_user_password="$2"
echo '0'
}
function install_interactive_turtl {
if [ ! "$ONION_ONLY" ]; then
ONION_ONLY='no'
fi
if [[ $ONION_ONLY != "no" ]]; then
TURTL_DOMAIN_NAME='notes.local'
write_config_param "TURTL_DOMAIN_NAME" "$TURTL_DOMAIN_NAME"
else
function_check interactive_site_details
interactive_site_details "turtl" "TURTL_DOMAIN_NAME" "TURTL_CODE"
fi
APP_INSTALLED=1
}
function turtl_disable_registrations {
if grep -q "$TURTL_SIGNUP_STRING" $turtl_users_file; then
if [ -f $turtl_users_file ]; then
cp $turtl_users_file $TURTL_BASE_DIR/.users.lisp
sed -i '/(route (:post "\/users") (req res)/,/(send-json res user))))/{//!d}' $turtl_users_file
sed -i 's|(send-json res user))))|())|g' $turtl_users_file
chown -R turtl:turtl $TURTL_BASE_DIR
systemctl restart turtl
fi
fi
}
function turtl_enable_registrations {
if ! grep -q "$TURTL_SIGNUP_STRING" $turtl_users_file; then
if [ -f $TURTL_BASE_DIR/.users.lisp ]; then
cp $TURTL_BASE_DIR/.users.lisp $turtl_users_file
rm $TURTL_BASE_DIR/.users.lisp
chown -R turtl:turtl $TURTL_BASE_DIR
systemctl restart turtl
fi
fi
}
function configure_interactive_turtl_signups {
# This implements a hack which removes or adds the function needed
# to sign up new users. It should eventually be removed once that
# capability exists within the api
dialog --title $"Allow new turtl signups" \
--backtitle $"Freedombone Control Panel" \
--defaultno \
--yesno $"\\nAllow registration of new users?" 10 60
sel=$?
case $sel in
0)
turtl_enable_registrations
dialog --title $"Allow new turtl signups" \
--msgbox $"New turtl user registrations are now allowed" 6 60
return;;
1)
turtl_disable_registrations
dialog --title $"Disable new turtl signups" \
--msgbox $"New turtl user registrations are now disabled" 6 60
return;;
255) return;;
esac
}
function configure_interactive_turtl_storage {
data=$(mktemp 2>/dev/null)
dialog --title $"Change storage limit" \
--backtitle $"Freedombone Control Panel" \
--inputbox $"Enter a storage limit in megabytes." 8 75 "$TURTL_STORAGE_LIMIT_MB" 2>"$data"
sel=$?
case $sel in
0)
STORAGE=$(<"$data")
if [ ${#STORAGE} -gt 0 ]; then
TURTL_STORAGE_LIMIT_MB=$STORAGE
sed -i "s|defparameter *default-storage-limit*.*|defparameter *default-storage-limit* ${TURTL_STORAGE_LIMIT_MB})|g" $TURTL_BASE_DIR/api/config/config.lisp
systemctl restart turtl
dialog --title $"Change storage limit" \
--msgbox $"Storage limit changed to ${TURTL_STORAGE_LIMIT_MB}M" 6 50
fi
;;
esac
rm -f "$data"
}
function configure_interactive_turtl {
data=$(mktemp 2>/dev/null)
dialog --backtitle $"Freedombone Control Panel" \
--title $"turtl app settings" \
--radiolist $"Choose an operation:" 12 70 3 \
1 $"Enable/disable new user registrations" off \
2 $"Change storage limit" off \
3 $"Exit" on 2> "$data"
sel=$?
case $sel in
1) rm -f "$data"
exit 1;;
255) rm -f "$data"
exit 1;;
esac
case $(cat "$data") in
1) configure_interactive_turtl_signups;;
2) configure_interactive_turtl_storage;;
3) rm -f "$data"
return;;
esac
rm -f "$data"
}
function reconfigure_turtl {
if [ -d $TURTL_BASE_DIR/data ]; then
rm -rf $TURTL_BASE_DIR/data/*
fi
}
function upgrade_turtl {
CURR_TURTL_COMMIT=$(get_completion_param "turtl commit")
if [[ "$CURR_TURTL_COMMIT" == "$TURTL_COMMIT" ]]; then
return
fi
read_config_param "TURTL_DOMAIN_NAME"
function_check set_repo_commit
set_repo_commit $TURTL_BASE_DIR/api "turtl commit" "$TURTL_COMMIT" $TURTL_REPO
# this is used as a crude way of disabling signups and so
# should be superceded in future
if [ -f $TURTL_BASE_DIR/.users.lisp ]; then
turtl_disable_registrations
fi
systemctl restart turtl
nginx_dissite $TURTL_DOMAIN_NAME
chown -R turtl:turtl $TURTL_BASE_DIR
nginx_ensite $TURTL_DOMAIN_NAME
}
function backup_local_turtl {
read_config_param "TURTL_DOMAIN_NAME"
source_directory=$TURTL_BASE_DIR
if [ -d $source_directory ]; then
dest_directory=turtl
function_check suspend_site
suspend_site ${TURTL_DOMAIN_NAME}
function_check backup_directory_to_usb
backup_directory_to_usb $source_directory $dest_directory
function_check restart_site
restart_site
fi
source_directory=/var/lib/rethinkdb
if [ -d $source_directory ]; then
dest_directory=rethinkdb
function_check suspend_site
suspend_site ${TURTL_DOMAIN_NAME}
function_check backup_directory_to_usb
backup_directory_to_usb $source_directory $dest_directory
function_check restart_site
restart_site
fi
}
function restore_local_turtl {
read_config_param "TURTL_DOMAIN_NAME"
if [ $TURTL_DOMAIN_NAME ]; then
temp_restore_dir=/root/tempturtl
restore_directory_from_usb $temp_restore_dir turtl
if [ -d ${temp_restore_dir}/etc/turtl ]; then
cp -r ${temp_restore_dir}/etc/turtl/* /etc/turtl/
else
cp -r ${temp_restore_dir}/* /etc/turtl/
fi
# shellcheck disable=SC2181
if [ ! "$?" = "0" ]; then
set_user_permissions
backup_unmount_drive
exit 36723
fi
rm -rf ${temp_restore_dir}
chown -R turtl:turtl $TURTL_BASE_DIR
temp_restore_dir=/root/temprethinkdb
restore_directory_from_usb $temp_restore_dir rethinkdb
if [ -d ${temp_restore_dir}/var/lib/rethinkdb ]; then
cp -r ${temp_restore_dir}/var/lib/rethinkdb/* /var/lib/rethinkdb/
else
cp -r ${temp_restore_dir}/* /var/lib/rethinkdb/
fi
# shellcheck disable=SC2181
if [ ! "$?" = "0" ]; then
set_user_permissions
backup_unmount_drive
exit 378324
fi
rm -rf ${temp_restore_dir}
fi
}
function backup_remote_turtl {
echo -n ''
}
function restore_remote_turtl {
echo -n ''
}
function remove_turtl {
if [ ! -d $TURTL_BASE_DIR ]; then
return
fi
systemctl stop turtl
systemctl disable turtl
rm /etc/systemd/system/turtl.service
systemctl daemon-reload
remove_rethinkdb
remove_app turtl
remove_completion_param install_turtl
sed -i '/turtl/d' "$COMPLETION_FILE"
nginx_dissite $TURTL_DOMAIN_NAME
if [ -f /etc/nginx/sites-available/$TURTL_DOMAIN_NAME ]; then
rm /etc/nginx/sites-available/$TURTL_DOMAIN_NAME
fi
remove_certs $TURTL_DOMAIN_NAME
function_check remove_onion_service
remove_onion_service turtl ${TURTL_ONION_PORT}
function_check remove_ddns_domain
remove_ddns_domain $TURTL_DOMAIN_NAME
rm -rf /etc/rethinkdb
rm -rf /var/lib/rethinkdb
rm -rf $TURTL_BASE_DIR
groupdel -f turtl
userdel -r turtl
}
function turtl_setup {
PIDFILE=${PIDFILE:-nil}
BINDADDR=${BINDADDR:-0.0.0.0}
BINDPORT=${BINDPORT:-8181}
PROD_ERR_HANDLING=${PROD_ERR_HANDLING:-t}
if [[ $ONION_ONLY == 'no' ]]; then
FQDN=${FQDN:-$TURTL_DOMAIN_NAME}
SITE_URL=${SITE_URL:-https://$TURTL_DOMAIN_NAME}
else
FQDN=${FQDN:-$TURTL_ONION_HOSTNAME}
SITE_URL=${SITE_URL:-http://$TURTL_ONION_HOSTNAME}
fi
ADMIN_EMAIL=${ADMIN_EMAIL:-$MY_EMAIL_ADDRESS}
EMAIL_FROM=${EMAIL_FROM:-noreply@$DEFAULT_DOMAIN_NAME}
SMTP_USER=${SMTP_USER:-}
SMTP_PASS=${SMTP_PASS:-}
DISPLAY_ERRORS=${DISPLAY_ERRORS:-t}
DEFAULT_STORAGE_LIMIT=${DEFAULT_STORAGE_LIMIT:-100}
STORAGE_INVITE_CREDIT=${STORAGE_INVITE_CREDIT:-25}
if [[ $ONION_ONLY == 'no' ]]; then
LOCAL_UPLOAD_URL=${LOCAL_UPLOAD_URL:-https://$TURTL_DOMAIN_NAME}
else
LOCAL_UPLOAD_URL=${LOCAL_UPLOAD_URL:-http://$TURTL_ONION_HOSTNAME}
fi
LOCAL_UPLOAD_PATH=${LOCAL_UPLOAD_PATH:-"$TURTL_BASE_DIR/data"}
AWS_S3_TOKEN=${AWS_S3_TOKEN:-(:token ''
:secret ''
:bucket ''
:endpoint 'https://s3.amazonaws.com')}
# generates the config-file
cat << __ENDCONFIG__ > $TURTL_BASE_DIR/api/config/config.lisp
(in-package :turtl)
(defparameter *root* (asdf:system-relative-pathname :turtl #P""))
(defparameter *pid-file* "${PIDFILE}")
(defvar *server-bind* "${BINDADDR}")
(defvar *server-port* ${BINDPORT})
(defvar *db-name* "turtl")
(defvar *db-host* "127.0.0.1")
(defvar *db-port* 28015)
(defvar *production-error-handling* ${PROD_ERR_HANDLING})
(defvar *enable-hsts-header* nil)
(defvar *site-url* "${SITE_URL}")
(defvar *api-path* "")
(defvar *admin-email* "${ADMIN_EMAIL}")
(defvar *email-from* "${EMAIL_FROM}")
(defvar *email-user* "${SMTP_USER}")
(defvar *email-pass* "${SMTP_PASS}")
(defvar *display-errors* ${DISPLAY_ERRORS})
(defparameter *default-storage-limit* ${DEFAULT_STORAGE_LIMIT})
(defparameter *storage-invite-credit* ${STORAGE_INVITE_CREDIT})
(vom:config :turtl :info)
(defvar *local-upload* "${LOCAL_UPLOAD_PATH}")
(defvar *local-upload-url* "${LOCAL_UPLOAD_URL}")
(defvar *amazon-s3* "${AWS_S3_TOKEN}")
__ENDCONFIG__
cat $TURTL_BASE_DIR/api/config/config.footer >> $TURTL_BASE_DIR/api/config/config.lisp
# start the turtl server
systemctl restart rethinkdb
if [ ! -f $TURTL_BASE_DIR/quicklisp/setup.lisp ]; then
echo $"$TURTL_BASE_DIR/quicklisp/setup.lisp was not found"
exit 6238234
fi
{ echo '[Unit]';
echo 'Description=Note taking service';
echo 'Documentation=http://turtl.it';
echo 'Requires=network.target';
echo 'Requires=rethinkdb.service';
echo 'After=network.target';
echo 'After=rethinkdb.service';
echo '';
echo '[Service]';
echo 'Type=simple';
echo 'User=turtl';
echo "WorkingDirectory=$TURTL_BASE_DIR/api/"; } > /etc/systemd/system/turtl.service
if [[ "$check_architecture" == *"64"* && "$check_architecture" != *"arm"* ]]; then
echo "ExecStart=$TURTL_BASE_DIR/ccl/lx86cl64 -l $TURTL_BASE_DIR/quicklisp/setup.lisp -l launch.lisp" >> /etc/systemd/system/turtl.service
else
if [[ "$check_architecture" != *"arm"* ]]; then
echo "ExecStart=$TURTL_BASE_DIR/ccl/lx86cl -l $TURTL_BASE_DIR/quicklisp/setup.lisp -l launch.lisp" >> /etc/systemd/system/turtl.service
else
echo "ExecStart=$TURTL_BASE_DIR/ccl/armcl -l $TURTL_BASE_DIR/quicklisp/setup.lisp -l launch.lisp" >> /etc/systemd/system/turtl.service
fi
fi
{ echo '';
echo '[Install]';
echo 'WantedBy=multi-user.target'; } >> /etc/systemd/system/turtl.service
chmod +x /etc/systemd/system/turtl.service
chown -R turtl:turtl $TURTL_BASE_DIR
systemctl enable turtl
systemctl daemon-reload
systemctl start turtl
}
function install_turtl_api {
# https://github.com/ArthurGarnier/turtl-docker
$INSTALL_PACKAGES wget libterm-readline-perl-perl gcc libuv1-dev
if [ ! -d $TURTL_BASE_DIR ]; then
mkdir -p $TURTL_BASE_DIR
fi
cd "$TURTL_BASE_DIR" || exit 745726542
mkdir cd $TURTL_BASE_DIR/data
check_architecture=$(uname -a)
# Install ccl
if [[ "$check_architecture" != *"arm"* ]]; then
wget -P $TURTL_BASE_DIR/ ftp://ftp.clozure.com/pub/release/1.11/ccl-1.11-linuxx86.tar.gz
mkdir -p $TURTL_BASE_DIR/ccl
tar xvzf $TURTL_BASE_DIR/ccl-1.11-linuxx86.tar.gz -C $TURTL_BASE_DIR/ccl --strip-components=1
else
wget -P $TURTL_BASE_DIR/ ftp://ftp.clozure.com/pub/release/1.11/ccl-1.11-linuxarm.tar.gz
mkdir -p $TURTL_BASE_DIR/ccl
tar xvzf $TURTL_BASE_DIR/ccl-1.11-linuxarm.tar.gz -C $TURTL_BASE_DIR/ccl --strip-components=1
fi
# install quicklisp
cat << __ENDCONFIG__ > $TURTL_BASE_DIR/quicklisp_install
(load (compile-file "asdf.lisp"))
(load (compile-file "quicklisp.lisp"))
(quicklisp-quickstart:install)
(ql:system-apropos "vecto")
(ql:quickload "alexandria")
(ql:quickload "babel")
(ql:quickload "blackbird")
(ql:quickload "bordeaux-threads")
(ql:quickload "cffi")
(ql:quickload "chipz")
(ql:quickload "chunga")
(ql:quickload "cl-annot")
(ql:quickload "cl-async")
(ql:quickload "cl-async-future")
(ql:quickload "cl-base64")
(ql:quickload "cl-fad")
(ql:quickload "cl-libuv")
(ql:quickload "cl-mongo-id")
(ql:quickload "cl-ppcre")
(ql:quickload "cl-rethinkdb")
(ql:quickload "cl-smtp")
(ql:quickload "cl+ssl")
(ql:quickload "cl-syntax")
(ql:quickload "cl-utilities")
(ql:quickload "cl-vectors")
(ql:quickload "do-urlencode")
(ql:quickload "drakma")
(ql:quickload "drakma-async")
(ql:quickload "event-glue")
(ql:quickload "fast-http")
(ql:quickload "fast-io")
(ql:quickload "flexi-streams")
(ql:quickload "ironclad")
(ql:quickload "jonathan")
(ql:quickload "local-time")
(ql:quickload "md5")
(ql:quickload "named-readtables")
(ql:quickload "nibbles")
(ql:quickload "proc-parse")
(ql:quickload "puri")
(ql:quickload "quri")
(ql:quickload "salza2")
(ql:quickload "secure-random")
(ql:quickload "smart-buffer")
(ql:quickload "split-sequence")
(ql:quickload "static-vectors")
(ql:quickload "trivial-backtrace")
(ql:quickload "trivial-features")
(ql:quickload "trivial-garbage")
(ql:quickload "trivial-gray-streams")
(ql:quickload "trivial-types")
(ql:quickload "usocket")
(ql:quickload "vecto")
(ql:quickload "vom")
(ql:quickload "wookie")
(ql:quickload "xmls")
(ql:quickload "xsubseq")
(ql:quickload "yason")
(ql:quickload "zpb-ttf")
(ql:quickload "zpng")
(ql:add-to-init-file)
(ccl::quit)
__ENDCONFIG__
if [ ! -f asdf.lisp ]; then
wget https://common-lisp.net/project/asdf/asdf.lisp
fi
if [ ! -f quicklisp.lisp ]; then
wget https://beta.quicklisp.org/quicklisp.lisp
fi
if [ -d $TURTL_BASE_DIR ]; then
chown -R turtl:turtl $TURTL_BASE_DIR
fi
adduser --disabled-login --home=$TURTL_BASE_DIR --gecos 'turtl' turtl
if [ ! -d $TURTL_BASE_DIR ]; then
echo $"$TURTL_BASE_DIR directory not created"
exit 263493
fi
groupadd turtl
chown -R turtl:turtl $TURTL_BASE_DIR
if [[ "$check_architecture" != *"arm"* ]]; then
if [[ "$check_architecture" == *"64"* ]]; then
su -c "cat $TURTL_BASE_DIR/quicklisp_install | $TURTL_BASE_DIR/ccl/lx86cl64" - turtl
else
su -c "cat $TURTL_BASE_DIR/quicklisp_install | $TURTL_BASE_DIR/ccl/lx86cl" - turtl
fi
else
su -c "cat $TURTL_BASE_DIR/quicklisp_install | $TURTL_BASE_DIR/ccl/larmcl" - turtl
fi
rm $TURTL_BASE_DIR/quicklisp_install
install_rethinkdb
echo "http-port=8091" > /etc/rethinkdb/instances.d/turtl.conf
chown -R rethinkdb:rethinkdb /var/lib/rethinkdb
# install turtl API
cd "$TURTL_BASE_DIR/" || exit 6428462
if [ -d /repos/turtl ]; then
mkdir -p $TURTL_BASE_DIR/api
cp -r -p /repos/turtl/. $TURTL_BASE_DIR/api
cd "$TURTL_BASE_DIR/api" || exit 57141845
git pull
else
git clone $TURTL_REPO $TURTL_BASE_DIR/api
fi
cd "$TURTL_BASE_DIR/api" || exit 35814614
git checkout $TURTL_COMMIT -b $TURTL_COMMIT
set_completion_param "turtl commit" "$TURTL_COMMIT"
cd "$TURTL_BASE_DIR/quicklisp/local-projects" || exit 43618941415
git clone git://github.com/orthecreedence/cl-hash-util
if [[ "$check_architecture" != *"arm"* ]]; then
if [[ "$check_architecture" == *"64"* ]]; then
su -c "cat '(ccl:quit)' | $TURTL_BASE_DIR/ccl/lx86cl64 -l $TURTL_BASE_DIR/quicklisp/setup.lisp" - turtl
else
su -c "cat '(ccl:quit)' | $TURTL_BASE_DIR/ccl/lx86cl -l $TURTL_BASE_DIR/quicklisp/setup.lisp" - turtl
fi
else
su -c "cat '(ccl:quit)' | $TURTL_BASE_DIR/ccl/larmcl -l $TURTL_BASE_DIR/quicklisp/setup.lisp" - turtl
fi
# config
{ echo '(defvar *enabled-cors-resources* "resource://turtl-at-lyonbros-dot-com"';
echo ' "When set, will enable CORS for resource:// origins if they match the given';
echo ' string. Entries should be comma separated (this string is passed verbatim in';
echo ' the Access-Control-Allow-Origin header).")';
echo '(defparameter *public-actions*';
echo " \`((:post . ,(concatenate 'string *api-path* \"/users\"))";
echo " (:post . ,(concatenate 'string *api-path* \"/log/error\"))";
echo ' (:post . "/cla/sign")';
echo ' (:get . "/ping")';
echo ' (:get . "/admin")';
echo " (:get . ,(cl-ppcre:create-scanner (concatenate 'string *api-path* \"/invites/codes/([0-9a-f-]+)\"))))";
echo " \"A list of public resources/actions that do not require authentication.\")";
echo "(defvar *analytics* '(:enabled t";
echo ' :db "analytics"))'; } > "$TURTL_BASE_DIR/api/config/config.footer"
cp $TURTL_BASE_DIR/asdf.lisp $TURTL_BASE_DIR/api
echo '(load (compile-file "asdf.lisp"))' > $TURTL_BASE_DIR/api/launch.lisp
echo "(pushnew \"./\" asdf:*central-registry* :test #'equal)" >> $TURTL_BASE_DIR/api/launch.lisp
echo '(load "start")' >> $TURTL_BASE_DIR/api/launch.lisp
TURTL_ONION_HOSTNAME=$(add_onion_service turtl 80 ${TURTL_ONION_PORT})
turtl_setup
}
function install_turtl_nginx {
turtl_nginx_site=/etc/nginx/sites-available/$TURTL_DOMAIN_NAME
if [[ $ONION_ONLY == "no" ]]; then
function_check nginx_http_redirect
nginx_http_redirect $TURTL_DOMAIN_NAME
{ echo 'server {';
echo ' listen 443 ssl;';
echo ' #listen [::]:443 ssl;';
echo " server_name ${TURTL_DOMAIN_NAME};";
echo '';
echo ' # Security'; } >> "$turtl_nginx_site"
function_check nginx_ssl
nginx_ssl $TURTL_DOMAIN_NAME
function_check nginx_security_options
nginx_security_options $TURTL_DOMAIN_NAME
{ echo ' add_header Strict-Transport-Security max-age=15768000;';
echo '';
echo ' # Logs';
echo ' access_log /dev/null;';
echo ' error_log /dev/null;';
echo '';
echo ' location / {'; } >> "$turtl_nginx_site"
function_check nginx_limits
nginx_limits $TURTL_DOMAIN_NAME '15m'
{ echo " proxy_pass http://localhost:${TURTL_PORT}/;";
echo " proxy_set_header Host \$host;";
echo ' proxy_buffering off;';
echo ' }';
echo '}'; } >> "$turtl_nginx_site"
else
echo -n '' > $turtl_nginx_site
fi
{ echo 'server {';
echo " listen 127.0.0.1:${TURTL_ONION_PORT};";
echo ' port_in_redirect off;';
echo " server_name ${TURTL_ONION_HOSTNAME};";
echo ''; } >> $turtl_nginx_site
function_check nginx_security_options
nginx_security_options $TURTL_DOMAIN_NAME
{ echo '';
echo ' # Logs';
echo ' access_log /dev/null;';
echo ' error_log /dev/null;';
echo '';
echo ' location / {'; } >> $turtl_nginx_site
function_check nginx_limits
nginx_limits $TURTL_DOMAIN_NAME '15m'
{ echo " proxy_pass http://localhost:${TURTL_PORT}/;";
echo " proxy_set_header Host \$host;";
echo ' proxy_buffering off;';
echo ' }';
echo '}'; } >> $turtl_nginx_site
function_check add_ddns_domain
add_ddns_domain $TURTL_DOMAIN_NAME
set_completion_param "turtl domain" "$TURTL_DOMAIN_NAME"
function_check create_site_certificate
create_site_certificate $TURTL_DOMAIN_NAME 'yes'
function_check nginx_ensite
nginx_ensite $TURTL_DOMAIN_NAME
systemctl restart nginx
}
function install_turtl {
install_turtl_api
install_turtl_nginx
APP_INSTALLED=1
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment