├── .gitignore ├── lib ├── nodejs.sh ├── memcached.sh ├── user.sh ├── ruby.sh ├── php.sh ├── security.sh ├── redis.sh ├── bluepill.sh ├── varnish.sh ├── hostname.sh ├── passenger.sh ├── postgresql.sh ├── wordpress.sh ├── git.sh ├── mysql.sh ├── utils.sh └── nginx.sh ├── install ├── shellstack.sh ├── recipes ├── basic ├── rails └── wordpress └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | -------------------------------------------------------------------------------- /lib/nodejs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function install_nodejs { 4 | apt-get -y install python-software-properties 5 | add-apt-repository ppa:chris-lea/node.js 6 | apt-get -y update 7 | apt-get -y install nodejs nodejs-dev 8 | } 9 | -------------------------------------------------------------------------------- /lib/memcached.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ########################################################### 4 | # memcached 5 | ########################################################### 6 | 7 | function install_memcached { 8 | log "Installing memcached..." 9 | aptitude install -y memcached 10 | } 11 | -------------------------------------------------------------------------------- /install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ROOT_PATH=$(dirname $(readlink -f $0)) 4 | LIB_PATH="$ROOT_PATH/lib" 5 | 6 | if [ ! -n "$1" ]; then 7 | echo "Usage: ./install " 8 | exit 1; 9 | fi 10 | 11 | RECIPE="$ROOT_PATH/recipes/$1" 12 | if [ -e $RECIPE ] ; then 13 | source "$RECIPE" 14 | fi 15 | 16 | install_`echo $1` 17 | -------------------------------------------------------------------------------- /shellstack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ROOT_PATH=$(dirname $(readlink -f $0)) 4 | LIB_PATH="$ROOT_PATH/lib" 5 | 6 | source "$LIB_PATH/hostname.sh" 7 | source "$LIB_PATH/user.sh" 8 | source "$LIB_PATH/utils.sh" 9 | source "$LIB_PATH/security.sh" 10 | source "$LIB_PATH/mysql.sh" 11 | source "$LIB_PATH/postgresql.sh" 12 | source "$LIB_PATH/nginx.sh" 13 | source "$LIB_PATH/git.sh" 14 | source "$LIB_PATH/wordpress.sh" 15 | source "$LIB_PATH/ruby.sh" 16 | source "$LIB_PATH/php.sh" 17 | source "$LIB_PATH/memcached.sh" 18 | source "$LIB_PATH/varnish.sh" 19 | source "$LIB_PATH/nodejs.sh" 20 | source "$LIB_PATH/redis.sh" 21 | source "$LIB_PATH/bluepill.sh" 22 | -------------------------------------------------------------------------------- /recipes/basic: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source "$LIB_PATH/utils.sh" 3 | source "$LIB_PATH/hostname.sh" 4 | source "$LIB_PATH/user.sh" 5 | source "$LIB_PATH/security.sh" 6 | 7 | function defaults_basic { 8 | #TODO: verify if vars are set and then use defautls our get 'em another way 9 | HOST_NAME="myhost" 10 | USER_NAME="myuser" 11 | USER_PASSWORD="mys3cr3t" 12 | USER_SSH_KEY="ssh-rsa paste here your ~/.ssh/id_rsa.pub" 13 | } 14 | 15 | function install_basic { 16 | upgrade_system 17 | install_essentials 18 | set_hostname $HOST_NAME 19 | update_locale_en_US_UTF_8 20 | create_deploy_user $USER_NAME $USER_PASSWORD "$USER_SSH_KEY" 21 | set_basic_security 22 | } 23 | -------------------------------------------------------------------------------- /lib/user.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function create_deploy_user { 4 | #$1 - USERNAME 5 | #$2 - PASSWORD 6 | #$3 - SSHKEY 7 | add_user $1 $2 "users,sudo" 8 | add_ssh_key $1 "$3" 9 | } 10 | 11 | function user_home { 12 | cat /etc/passwd | grep "^$1:" | cut --delimiter=":" -f6 13 | } 14 | 15 | function add_user { 16 | #$1 - USERNAME 17 | #$2 - PASSWORD 18 | #$3 - GROUPS 19 | log "Adding user $1..." 20 | useradd --create-home --shell "/bin/bash" --user-group --groups "$3" "$1" 21 | echo "$1:$2" | chpasswd 22 | } 23 | 24 | function add_ssh_key { 25 | #$1 - USERNAME 26 | #$2 - SSHKEY 27 | log "Trusting informed public ssh key for user $1..." 28 | USER_HOME=$(user_home "$1") 29 | sudo -u "$1" mkdir "$USER_HOME/.ssh" 30 | sudo -u "$1" touch "$USER_HOME/.ssh/authorized_keys" 31 | sudo -u "$1" echo "$2" >> "$USER_HOME/.ssh/authorized_keys" 32 | chmod 0600 "$USER_HOME/.ssh/authorized_keys" 33 | } 34 | -------------------------------------------------------------------------------- /lib/ruby.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ###################### 4 | # Ruby/RubyGem/Rails # 5 | ###################### 6 | 7 | function install_ruby 8 | { 9 | cd /usr/local/src 10 | RUBY_VERSION=ruby-1.9.2-$RUBY_RELEASE 11 | wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/$RUBY_VERSION.tar.gz 12 | tar xzf $RUBY_VERSION.tar.gz 13 | cd $RUBY_VERSION 14 | ./configure 15 | make 16 | make install 17 | } 18 | 19 | function create_gemrc { 20 | cat > ~/.gemrc << EOF 21 | verbose: true 22 | bulk_treshold: 1000 23 | install: --no-ri --no-rdoc --env-shebang 24 | benchmark: false 25 | backtrace: false 26 | update: --no-ri --no-rdoc --env-shebang 27 | update_sources: true 28 | EOF 29 | cp ~/.gemrc $USER_HOME 30 | chown $USER_NAME:$USER_NAME $USER_HOME/.gemrc 31 | } 32 | 33 | function update_rubygems { 34 | gem update --system 35 | } 36 | 37 | function set_rails_production_environment { 38 | cat >> /etc/environment << EOF 39 | RAILS_ENV=$R_ENV 40 | RACK_ENV=$R_ENV 41 | EOF 42 | } 43 | 44 | function install_bundler { 45 | gem install bundler 46 | } 47 | -------------------------------------------------------------------------------- /recipes/rails: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source "$ROOT_PATH/recipes/basic" 3 | source "$LIB_PATH/ruby.sh" 4 | source "$LIB_PATH/nodejs.sh" 5 | source "$LIB_PATH/passenger.sh" 6 | source "$LIB_PATH/bluepill.sh" 7 | source "$LIB_PATH/redis.sh" 8 | source "$LIB_PATH/mysql.sh" 9 | source "$LIB_PATH/postgresql.sh" 10 | 11 | function defaults_rails { 12 | DATABASE_TYPE="mysql" 13 | DATABASE_PASSWORD="mydbs3cr3t" 14 | R_ENV="production" 15 | RUBY_RELEASE="p290" 16 | REDIS_VERSION="2.2.4" 17 | } 18 | 19 | function install_rails { 20 | install_basic 21 | install_ruby 22 | install_nodejs 23 | create_gemrc 24 | update_rubygems 25 | install_passenger_with_nginx 26 | set_rails_production_environment 27 | install_bundler 28 | install_bluepill 29 | install_redis 30 | case "$DATABASE_TYPE" in 31 | mysql) 32 | install_mysql $DATABASE_PASSWORD && tune_mysql 40 33 | ;; 34 | pgsql) 35 | install_postgresql $DATABASE_PASSWORD 36 | ;; 37 | *) 38 | install_mysql $DATABASE_PASSWORD && tune_mysql 40 39 | install_postgresql $DATABASE_PASSWORD 40 | ;; 41 | esac 42 | } 43 | -------------------------------------------------------------------------------- /recipes/wordpress: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source "$ROOT_PATH/recipes/basic" 3 | source "$LIB_PATH/mysql.sh" 4 | source "$LIB_PATH/memcached.sh" 5 | source "$LIB_PATH/varnish.sh" 6 | source "$LIB_PATH/nginx.sh" 7 | source "$LIB_PATH/php.sh" 8 | source "$LIB_PATH/wordpress.sh" 9 | 10 | function defaults_wordpress { 11 | MYSQL_ROOT_PASSWORD="mydbs3cr3t" 12 | WP_DOMAIN="mydomain.com" 13 | WP_MYSQL_USERNAME='myuser' 14 | WP_MYSQL_PASSWORD='mydbs3cr3t' 15 | WP_DATABASE_NAME='mydb_wp' 16 | WP_USERNAME='myuser' 17 | WP_PASSWORD='mys3cr3t' 18 | WP_EMAIL='my@email.com' 19 | WP_PUBLIC_BLOG=1 20 | } 21 | 22 | function install_wordpress { 23 | install_basic 24 | install_mysql $MYSQL_ROOT_PASSWORD && tune_mysql 40 25 | install_memcached 26 | install_nginx 27 | install_php5_fpm 28 | install_varnish 29 | setup_varnish_wordpress_vcl 30 | setup_php5_fpm_with_nginx 31 | create_nginx_wordpress_site $WP_DOMAIN 32 | enable_nginx_site wordpress 33 | disable_nginx_site default 34 | install_wordpress_site $MYSQL_ROOT_PASSWORD $WP_MYSQL_USERNAME $WP_MYSQL_PASSWORD $WP_DATABASE_NAME $WP_DOMAIN $WP_USERNAME $WP_PASSWORD $WP_EMAIL $WP_PUBLIC_BLOG 35 | } 36 | -------------------------------------------------------------------------------- /lib/php.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function install_php5_fpm { 4 | log "Installing php5 fpm..." 5 | mkdir -p /var/www 6 | aptitude -y install php5-fpm php5-curl php5-mysql php5-memcache php-apc php5-pgsql php5-common php5-suhosin php5-cli php5-imagick php5-gd 7 | 8 | php_fpm_conf_file=`grep -R "^listen.*=.*127" /etc/php5/fpm/* | sed 's/:.*$//g' | uniq | head -n 1` 9 | #sockets > ports. Using the 127.0.0.1:9000 stuff needlessly introduces TCP/IP overhead. 10 | sed -i 's/listen = 127.0.0.1:9000/listen = \/var\/run\/php5-fpm.sock/' $php_fpm_conf_file 11 | 12 | #sockets limited by net.core.somaxconn and listen.backlog to 128 by default, so increase this 13 | #see http://www.saltwaterc.eu/nginx-php-fpm-for-high-loaded-websites.html 14 | sed -i 's/^.*listen.backlog.*$/listen.backlog = 1024/g' $php_fpm_conf_file 15 | echo "net.core.somaxconn=1024" >/etc/sysctl.d/10-unix-sockets.conf 16 | sysctl net.core.somaxconn=1024 17 | 18 | #set max requests to deal with any possible memory leaks 19 | sed -i 's/^.*pm.max_requests.*$/pm.max_requests = 1024/g' $php_fpm_conf_file 20 | /etc/init.d/php5-fpm restart 21 | } 22 | 23 | function setup_php5_fpm_with_nginx { 24 | cat > /etc/nginx/conf.d/php5-fpm.conf << EOF 25 | upstream php5-fpm-sock { 26 | server unix:/var/run/php5-fpm.sock; 27 | } 28 | EOF 29 | } 30 | -------------------------------------------------------------------------------- /lib/security.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################# 4 | # Security # 5 | ################################# 6 | 7 | function set_basic_security { 8 | log "Setting up basic security..." 9 | install_fail2ban 10 | install_ufw 11 | basic_ufw_setup 12 | sshd_permit_root_login No 13 | sshd_password_authentication No 14 | sshd_pub_key_authentication Yes 15 | /etc/init.d/ssh restart 16 | } 17 | 18 | function install_fail2ban { 19 | aptitude -y install fail2ban 20 | } 21 | 22 | function install_ufw { 23 | aptitude -y install ufw 24 | } 25 | 26 | function basic_ufw_setup { 27 | # see https://help.ubuntu.com/community/UFW 28 | ufw logging on 29 | ufw default deny 30 | ufw allow ssh 31 | ufw allow http 32 | ufw allow https 33 | ufw enable 34 | } 35 | 36 | function security_logcheck { 37 | aptitude -y install logcheck logcheck-database 38 | } 39 | 40 | function sshd_edit_bool { 41 | # $1 - param name 42 | # $2 - Yes/No 43 | VALUE=`lower $2` 44 | if [ "$VALUE" == "yes" ] || [ "$VALUE" == "no" ]; then 45 | sed -i "s/^#*\($1\).*/\1 $VALUE/" /etc/ssh/sshd_config 46 | fi 47 | } 48 | 49 | function sshd_permit_root_login { 50 | sshd_edit_bool "PermitRootLogin" "$1" 51 | } 52 | 53 | function sshd_password_authentication { 54 | sshd_edit_bool "PasswordAuthentication" "$1" 55 | } 56 | 57 | function sshd_pub_key_authentication { 58 | sshd_edit_bool "PubkeyAuthentication" "$1" 59 | } 60 | 61 | function sshd_password_authentication { 62 | sshd_edit_bool "PasswordAuthentication" "$1" 63 | } 64 | -------------------------------------------------------------------------------- /lib/redis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function install_redis { 4 | cd /usr/local/src 5 | wget http://redis.googlecode.com/files/redis-$REDIS_VERSION.tar.gz 6 | tar xvzf redis-$REDIS_VERSION.tar.gz 7 | cd redis-$REDIS_VERSION 8 | make 9 | make install 10 | mkdir -p /var/lib/redis 11 | mkdir -p /var/log/redis 12 | /usr/sbin/useradd --system --user-group --home-dir /var/lib/redis redis 13 | chown redis.redis /var/lib/redis 14 | chown redis.redis /var/log/redis 15 | wget "https://github.com/ijonas/dotfiles/raw/master/etc/init.d/redis-server" -O /etc/init.d/redis-server 16 | chmod +x /etc/init.d/redis-server 17 | /usr/sbin/update-rc.d -f redis-server defaults 18 | cat > /etc/redis.conf << EOF 19 | daemonize yes 20 | pidfile /var/run/redis.pid 21 | port 6379 22 | timeout 0 23 | loglevel verbose 24 | logfile /var/log/redis/redis.log 25 | databases 16 26 | save 900 1 27 | save 300 10 28 | save 60 10000 29 | rdbcompression yes 30 | dbfilename dump.rdb 31 | dir ./ 32 | slave-serve-stale-data yes 33 | appendonly no 34 | appendfsync everysec 35 | no-appendfsync-on-rewrite no 36 | auto-aof-rewrite-percentage 100 37 | auto-aof-rewrite-min-size 64mb 38 | slowlog-log-slower-than 10000 39 | slowlog-max-len 1024 40 | vm-enabled no 41 | vm-swap-file /tmp/redis.swap 42 | vm-max-memory 0 43 | vm-page-size 32 44 | vm-pages 134217728 45 | vm-max-threads 4 46 | hash-max-zipmap-entries 512 47 | hash-max-zipmap-value 64 48 | list-max-ziplist-entries 512 49 | list-max-ziplist-value 64 50 | set-max-intset-entries 512 51 | zset-max-ziplist-entries 128 52 | zset-max-ziplist-value 64 53 | activerehashing yes 54 | EOF 55 | /etc/init.d/redis-server start 56 | } 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ShellStack 2 | ===== 3 | 4 | ShellStack is a set of shell scripts that I've been collecting and creating to ease the installation of applications. 5 | 6 | At this time, my daily working environment is based on Ubuntu Linux, therefore all scripts should work on the latest LTS versions. 7 | 8 | Recipes 9 | ----- 10 | 11 | Although you can use ShellStack's files separately, it has some pre cooked recipes to expedite server setup. Currently there are basically three recipes: 12 | 13 | * basic - installs a current and secure basic box with some essential packages on it 14 | * wordpress - install a production ready WP environment for users that have heavy traffic needs 15 | * rails - installs a Ruby on Rails ready box based on Basic with production ready capabilities 16 | 17 | Usage 18 | ----- 19 | 20 | You can just source `shellstack.sh` file to source all the script files and call the functions inside the lib directory or you can also use one of the recipes listed above by issuing on terminal: 21 | 22 | `./install ` 23 | 24 | Motivation 25 | ----- 26 | 27 | As a big [Linode](http://linode.com) fan, and understanding that their StackScript platform is too simple to keep complex scripts on a form field I decided to organize things better with a git project with good file separation and keep a bare minimum of scripting inside the StackScript just to clone the git repository and fire installation. You can find the scripts [here](http://www.linode.com/stackscripts/browse/?ss_keyword=fagiani) 28 | 29 | Contributing 30 | ----- 31 | 32 | Please feel free to fork and send pull requests with your contributions! 33 | 34 | Author 35 | ----- 36 | 37 | [Paulo Fagiani](https://github.com/fagiani) 38 | 39 | Thanks 40 | ----- 41 | 42 | [Linode StackScripts](http://linode.com/stackscripts) 43 | 44 | [Eric Bishop](http://github.com/ericpaulbishop) 45 | -------------------------------------------------------------------------------- /lib/bluepill.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function install_bluepill { 4 | gem install bluepill 5 | echo "local6.* /var/log/bluepill.log" > /etc/rsyslog.d/bluepill.conf 6 | sed -i '/\/var\/log\/messages/i/var/log/bluepill.log' /etc/logrotate.d/rsyslog 7 | mkdir -p /var/bluepill/pids /var/bluepill/socks 8 | echo "$USER_NAME ALL=(ALL) NOPASSWD:/usr/local/bin/bluepill" >> /etc/sudoers 9 | cat > /etc/init.d/bluepill << EOF 10 | #!/bin/sh 11 | 12 | # Author: Jon Kinney 13 | # Based on the opensuse skeleton /etc/init.d/skeleton init script 14 | 15 | ### BEGIN INIT INFO 16 | # Provides: bluepill 17 | # Required-Start: 18 | # Required-Stop: 19 | # Default-Start: 2 3 4 5 20 | # Default-Stop: 0 1 6 21 | # Short-Description: bluepill daemon, providing process monitoring 22 | # Description: bluepill is a monitoring tool. More info at http://github.com/arya/bluepill. 23 | ### END INIT INFO 24 | 25 | export PATH="/usr/local/bin:\$PATH" 26 | 27 | # Check for missing binaries 28 | BLUEPILL_BIN=/usr/local/bin/bluepill 29 | test -x \$BLUEPILL_BIN || { echo "\$BLUEPILL_BIN not installed"; 30 | if [ "\$1" = "stop" ]; then exit 0; 31 | else exit 5; fi; } 32 | 33 | # Check for existence of needed config file and read it 34 | BLUEPILL_CONFIG=/etc/bluepill.conf 35 | test -r \$BLUEPILL_CONFIG || { echo "\$BLUEPILL_CONFIG not existing"; 36 | if [ "\$1" = "stop" ]; then exit 0; 37 | else exit 6; fi; } 38 | 39 | case "\$1" in 40 | start) 41 | echo -n "Starting bluepill " 42 | \$BLUEPILL_BIN load \$BLUEPILL_CONFIG 43 | ;; 44 | stop) 45 | echo -n "Shutting down bluepill " 46 | \$BLUEPILL_BIN quit 47 | ;; 48 | restart) 49 | ## Stop the service and regardless of whether it was 50 | ## running or not, start it again. 51 | \$0 stop 52 | \$0 start 53 | ;; 54 | *) 55 | echo "Usage: \$0 {start|stop|restart}" 56 | exit 1 57 | ;; 58 | esac 59 | EOF 60 | chmod +x /etc/init.d/bluepill 61 | /usr/sbin/update-rc.d -f bluepill defaults 62 | cat > /etc/bluepill.conf << EOF 63 | #just include here in ruby language your bluepill config 64 | EOF 65 | } 66 | -------------------------------------------------------------------------------- /lib/varnish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ########################################################### 4 | # varnish 5 | ########################################################### 6 | 7 | function install_varnish { 8 | log "Installing varnish..." 9 | aptitude install -y varnish 10 | echo "apc.shm_size=100M" >> /etc/php5/fpm/conf.d/apc.ini 11 | /etc/init.d/varnish restart 12 | /etc/init.d/nginx restart 13 | } 14 | 15 | function setup_varnish_wordpress_vcl { 16 | log "Setting up varnish wordpress.vcl..." 17 | cat > /etc/varnish/wordpress.vcl << EOF 18 | backend default { 19 | .host = "127.0.0.1"; 20 | .port = "8080"; 21 | } 22 | acl purge { 23 | "localhost"; 24 | } 25 | sub vcl_recv { 26 | if (req.request == "PURGE") { 27 | if (!client.ip ~ purge) { 28 | error 405 "Not allowed."; 29 | } 30 | return(lookup); 31 | } 32 | if (req.url ~ "^/$") { 33 | unset req.http.cookie; 34 | } 35 | } 36 | sub vcl_hit { 37 | if (req.request == "PURGE") { 38 | set obj.ttl = 0s; 39 | error 200 "Purged."; 40 | } 41 | } 42 | sub vcl_miss { 43 | if (req.request == "PURGE") { 44 | error 404 "Not in cache."; 45 | } 46 | if (!(req.url ~ "wp-(login|admin)")) { 47 | unset req.http.cookie; 48 | } 49 | if (req.url ~ "^/[^?]+.(jpeg|jpg|png|gif|ico|js|css|txt|gz|zip|lzma|bz2|tgz|tbz|html|htm)(\?.|)$") { 50 | unset req.http.cookie; 51 | set req.url = regsub(req.url, "\?.$", ""); 52 | } 53 | if (req.url ~ "^/$") { 54 | unset req.http.cookie; 55 | } 56 | } 57 | sub vcl_fetch { 58 | if (req.url ~ "^/$") { 59 | unset beresp.http.set-cookie; 60 | } 61 | if (!(req.url ~ "wp-(login|admin)")) { 62 | unset beresp.http.set-cookie; 63 | } 64 | } 65 | EOF 66 | IP_ADDRESS=$(system_ip) 67 | log "Ip address found: $IP_ADDRESS" 68 | sed -i "s/:6081/$IP_ADDRESS:80/" /etc/default/varnish 69 | sed -i "s/default.vcl/wordpress.vcl/" /etc/default/varnish 70 | sed -i "s/malloc,256m/file,\/var\/lib\/varnish\/\$INSTANCE\/varnish_storage.bin,1G/" /etc/default/varnish 71 | /etc/init.d/varnish restart 72 | /etc/init.d/php5-fpm stop 73 | /etc/init.d/php5-fpm start 74 | } 75 | -------------------------------------------------------------------------------- /lib/hostname.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################# 4 | # Hostname # 5 | ################################# 6 | 7 | function set_hostname 8 | { 9 | # $1 - HOSTNAME 10 | if [ ! -n "$1" ]; then 11 | log "set_hostname() requires the hostname as its first argument" 12 | return 1; 13 | fi 14 | 15 | log "Setting hostname to $1..." 16 | echo "$1" > /etc/hostname 17 | echo "$1" > /proc/sys/kernel/hostname 18 | 19 | touch /etc/hosts 20 | cat /etc/hosts | grep -v "$1" > /etc/hosts.tmp 21 | echo -e "\n127.0.0.1 $1\n" >> /etc/hosts.tmp 22 | mv /etc/hosts.tmp /etc/hosts 23 | } 24 | 25 | function backup_hostname 26 | { 27 | if [ ! -n "$1" ]; then 28 | log "backup_hostname() requires the backup directory as its first argument" 29 | return 1; 30 | fi 31 | 32 | local BACKUP_DIR="$1" 33 | 34 | if [ -e /etc/hostname ] ; then 35 | cp /etc/hostname "$BACKUP_DIR/" 36 | fi 37 | if [ -e /etc/hosts ] ; then 38 | cp /etc/hosts "$BACKUP_DIR/" 39 | fi 40 | if [ -e /etc/mailname ] ; then 41 | cp /etc/mailname "$BACKUP_DIR/" 42 | fi 43 | } 44 | 45 | function restore_hostname 46 | { 47 | if [ ! -n "$1" ]; then 48 | log "restore_hostname() requires the backup directory as its first argument" 49 | return 1; 50 | fi 51 | 52 | local BACKUP_DIR="$1" 53 | 54 | if [ -e "$BACKUP_DIR/hostname" ] ; then 55 | cp "$BACKUP_DIR/hostname" /etc/hostname 56 | hostname $(cat /etc/hostname) 57 | fi 58 | if [ -e "$BACKUP_DIR/hosts" ] ; then 59 | cp "$BACKUP_DIR/hosts" /etc/hosts 60 | fi 61 | if [ -e "$BACKUP_DIR/mailname" ] ; then 62 | cp "$BACKUP_DIR/mailname" /etc/mailname 63 | fi 64 | } 65 | 66 | function system_ip 67 | { 68 | dev=$(ifconfig | grep "Ethernet" | awk ' { print $1 } ' | head -n 1) 69 | if [ -z "$dev" ] ; then 70 | echo $(ifconfig eth0 | awk -F: '/inet addr:/ {print $2}' | awk '{ print $1 }') 71 | else 72 | echo $(ifconfig $dev | awk -F: '/inet addr:/ {print $2}' | awk '{ print $1 }') 73 | fi 74 | } 75 | 76 | function get_rdns_for_ip 77 | { 78 | # calls host on an IP address and returns its reverse dns 79 | if [ ! -e /usr/bin/host ]; then 80 | aptitude -y install dnsutils > /dev/null 81 | fi 82 | echo $(host $1 | awk '/pointer/ {print $5}' | sed 's/\.$//') 83 | } 84 | 85 | function get_rdns 86 | { 87 | # returns the reverse dns of the primary IP assigned to this system 88 | echo $(get_rdns $(system_ip)) 89 | } 90 | -------------------------------------------------------------------------------- /lib/passenger.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function install_passenger_with_nginx { 4 | gem install passenger 5 | PASSENGER_PATH=`passenger-config --root`/ext/nginx 6 | cd /usr/local/src 7 | NGINX_VERSION="nginx-$NGINX_RELEASE" 8 | wget "http://nginx.org/download/$NGINX_VERSION.tar.gz" 9 | tar xzf $NGINX_VERSION.tar.gz 10 | cd $NGINX_VERSION 11 | ./configure --prefix=/usr/local --sbin-path=/usr/local/sbin --conf-path=/etc/nginx/nginx.conf --with-http_ssl_module --with-http_gzip_static_module --add-module=$PASSENGER_PATH --with-http_sub_module 12 | cp -r conf /etc/nginx 13 | make && make install 14 | wget "http://library.linode.com/assets/660-init-deb.sh" -O /etc/init.d/nginx 15 | sed -i 's/\/opt\/nginx/\/usr\/local/g' /etc/init.d/nginx 16 | chmod +x /etc/init.d/nginx 17 | /usr/sbin/update-rc.d -f nginx defaults 18 | mkdir -p /var/log/nginx /etc/nginx/conf.d /etc/nginx/sites-available /etc/nginx/sites-enabled 19 | cat < /etc/logrotate.d/nginx 20 | /var/log/nginx/*.log { 21 | daily 22 | missingok 23 | rotate 52 24 | compress 25 | defaultslaycompress 26 | notifempty 27 | create 0640 www-data adm 28 | sharedscripts 29 | postrotate 30 | [ ! -f /var/run/nginx.pid ] || kill -USR1 \`cat /var/run/nginx.pid\` 31 | endscriptript 32 | } 33 | EOF 34 | cat < /etc/nginx/conf.d/passenger.conf 35 | passenger_root /usr/local/lib/ruby/gems/1.9.1/gems/passenger-3.0.11; 36 | passenger_ruby /usr/local/bin/ruby; 37 | EOF 38 | cat < /etc/nginx/nginx.conf 39 | user www-data; 40 | worker_processes 6; 41 | pid /var/run/nginx.pid; 42 | 43 | events { 44 | worker_connections 1024; 45 | } 46 | 47 | http { 48 | tcp_nodelay on; 49 | keepalive_timeout 65; 50 | types_hash_max_size 2048; 51 | 52 | include /etc/nginx/mime.types; 53 | default_type application/octet-stream; 54 | 55 | access_log /var/log/nginx/access.log; 56 | error_log /var/log/nginx/error.log; 57 | 58 | include /etc/nginx/conf.d/*.conf; 59 | include /etc/nginx/sites-enabled/*; 60 | } 61 | EOF 62 | cat < /etc/nginx/sites-available/default 63 | server { 64 | listen 80; 65 | server_name $DOMAIN_NAME; 66 | root /home/$USER_NAME/production/current/public; 67 | passenger_enabled on; 68 | access_log /var/log/nginx/app.access.log; 69 | error_log /var/log/nginx/app.error.log; 70 | gzip on; 71 | gzip_http_version 1.1; 72 | gzip_comp_level 6; 73 | gzip_proxied any; 74 | gzip_min_length 1024; 75 | gzip_buffers 16 8k; 76 | gzip_types text/plain text/html text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; 77 | gzip_vary on; 78 | gzip_disable “MSIE [1-6].(?!.*SV1)”; 79 | } 80 | EOF 81 | ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default 82 | /etc/init.d/nginx start 83 | } 84 | -------------------------------------------------------------------------------- /lib/postgresql.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function install_postgresql 4 | { 5 | apt-add-repository ppa:pitti/postgresql 6 | apt-get -y update 7 | aptitude -y install postgresql postgresql-contrib postgresql-dev postgresql-client libpq-dev 8 | pg_conf=$(find /etc/ -name "pg_hba.conf" | head -n 1) 9 | sed -i -e 's/^.*local.*all.*all.*$/local\tall\tall\tmd5/g' $pg_conf 10 | /etc/init.d/postgresql restart 11 | } 12 | 13 | function tune_postgresql 14 | { 15 | # Tunes PostgreSQL's memory usage to utilize the percentage of memory you 16 | # specify, defaulting to 30% 17 | # 18 | # $1 - the percent of system memory to allocate towards PgSQL 19 | if [ -z "$1" ] ; then 20 | PERCENT=30 21 | else 22 | PERCENT=$1 23 | fi 24 | TOTMEM=$(awk '/MemTotal/ {print int($2/1024)}' /proc/meminfo) # how much memory in MB this system has 25 | PGMEM=$((TOTMEM*PERCENT/100)) # how much memory we'd like to tune pgsql with 26 | 27 | pg_conf=$(find /etc/ -name "postgresql.conf" | head -n 1) 28 | sed -i -e 's/^.*shared_buffers.*$/shared_buffers = '$PGMEM'MB/g' $pg_conf 29 | #there is still need to increase SHMMAX at /proc/sys/kernel/shmmax in order to work but not sure on how much to automate 30 | /etc/init.d/postgresql restart 31 | } 32 | 33 | function postgresql_create_user 34 | { 35 | # $1 - the user to create 36 | # $2 - their password 37 | # $3 - allow user to create db? 38 | if [ -z "$1" ] ; then 39 | echo "postgresql_create_user() requires the username as its first argument" 40 | return 1; 41 | fi 42 | if [ -z "$2" ] ; then 43 | echo "postgresql_create_user() requires the user password to set as the second argument" 44 | return 1; 45 | fi 46 | echo "CREATE ROLE $1 WITH LOGIN ENCRYPTED PASSWORD '$2';" | sudo -u postgres psql 47 | 48 | if [ -n "$3" ] ; then 49 | if [ "$3" = "1" ] ; then 50 | echo "ALTER ROLE $1 WITH CREATEDB;" | sudo -u postgres psql 51 | fi 52 | fi 53 | } 54 | 55 | function postgresql_grant_user 56 | { 57 | # $1 - the user to bestow privileges 58 | # $2 - the database 59 | 60 | if [ -z "$1" ] ; then 61 | echo "postgresql_grant_user() requires username as the first argument" 62 | return 1; 63 | fi 64 | if [ -z "$2" ] ; then 65 | echo "postgresql_grant_user() requires a database as the second argument" 66 | return 1; 67 | fi 68 | echo "GRANT ALL PRIVILEGES ON DATABASE $2 TO $1 ;" | sudo -u postgres psql 69 | 70 | } 71 | 72 | function postgresql_create_database 73 | { 74 | # $1 - the db name to create 75 | 76 | if [ -z "$1" ] ; then 77 | echo "postgresql_create_database() requires the name of the database as the first argument" 78 | return 1; 79 | fi 80 | 81 | sudo -u postgres createdb --owner=postgres $1 82 | } 83 | 84 | function backup_postgresql 85 | { 86 | if [ -z "$1" ] ; then 87 | echo "backup_postgresql() requires the backup directory as its first argument" 88 | return 1; 89 | fi 90 | 91 | local BACKUP_DIR="$1" 92 | mkdir -p "$BACKUP_DIR" 93 | 94 | sudo -u postgres pg_dumpall >/tmp/all-db-postgres.sql 95 | local curdir=$(pwd) 96 | cd /tmp 97 | rm -rf "$BACKUP_DIR/all-db-postgres.tar.bz2" 98 | tar cjf "$BACKUP_DIR/all-db-postgres.tar.bz2" "all-db-postgres.sql" 99 | rm -rf "all-db-postgres.sql" 100 | cd "$curdir" 101 | } 102 | 103 | function restore_postgresql 104 | { 105 | if [ -z "$1" ] ; then 106 | echo "restore_postgresql() requires the backup directory as its first argument" 107 | return 1; 108 | fi 109 | 110 | local BACKUP_DIR="$1" 111 | 112 | if [ -e "$BACKUP_DIR/all-db-postgres.tar.bz2" ] ; then 113 | rm -rf /tmp/tmp.db 114 | mkdir /tmp/tmp.db 115 | tar -C "/tmp/tmp.db" -xjf "$BACKUP_DIR/all-db-postgres.tar.bz2" 116 | if [ -e /tmp/tmp.db/all-db-postgres.sql ] ; then 117 | cat /tmp/tmp.db/all-db-postgres.sql | sudo -u postgres psql 118 | fi 119 | rm -rf /tmp/tmp.db 120 | fi 121 | } 122 | -------------------------------------------------------------------------------- /lib/wordpress.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function install_wordpress_site { 4 | #$1 - MySQL root password 5 | #$2 - MySQL WordPress user 6 | #$3 - MySQL WordPress password 7 | #$4 - Wordpress Database name 8 | #$5 - Site URL 9 | #$6 - WP admin name 10 | #$7 - WP admin password 11 | #$8 - WP admin email 12 | #$9 - Public Blog? 0 - no | 1 - yes 13 | log "Intalling WordPress..." 14 | download_and_unzip_wordpress 15 | create_wordpress_database_user_and_tables $2 $3 $4 $1 16 | setup_wordpress_configuration $2 $3 $4 17 | trigger_wordpress_installation $5 $6 $7 $8 $9 18 | } 19 | 20 | function download_and_unzip_wordpress { 21 | log "Downloading and extracting WordPress..." 22 | wget "http://wordpress.org/latest.tar.gz" -O /var/www/wp-latest.tar.gz 23 | tar xfz /var/www/wp-latest.tar.gz -C /var/www 24 | } 25 | 26 | function create_wordpress_database_user_and_tables { 27 | #$1 - MySQL user 28 | #$2 - MySQL password 29 | #$3 - Wordpress Database name 30 | #$4 - MySQL root pasword 31 | log "Creating WordPress database and user..." 32 | create_mysql_database "$4" "$3" 33 | create_mysql_user "$4" "$1" "$2" 34 | grant_mysql_user "$4" "$1" "$3" 35 | } 36 | 37 | function setup_wordpress_configuration { 38 | #$1 - MySQL user 39 | #$2 - MySQL password 40 | #$3 - Wordpress Database name 41 | log "Setting up WordPress initial configuration..." 42 | mv /var/www/wordpress/wp-config-sample.php /var/www/wordpress/wp-config.php 43 | SALT=$(curl -L https://api.wordpress.org/secret-key/1.1/salt/) 44 | WP_CONFIG=/var/www/wordpress/wp-config.php 45 | chmod 640 $WP_CONFIG 46 | printf '%s\n' "g/put your unique phrase here/d" a "$SALT" . w | ed -s $WP_CONFIG 47 | sed -i "s/database_name_here/$3/" $WP_CONFIG 48 | sed -i "s/username_here/$1/" $WP_CONFIG 49 | sed -i "s/password_here/$2/" $WP_CONFIG 50 | sed -i "s/ 73 | EOF 74 | } 75 | 76 | function download_and_unzip_wp_cache_plugin { 77 | WP_CACHE_PATH=/var/www/wordpress/wp-content/plugins 78 | wget http://downloads.wordpress.org/plugin/wp-super-cache.0.9.9.9.zip -O $WP_CACHE_PATH/wp-super-cache.0.9.9.9.zip 79 | unzip $WP_CACHE_PATH/wp-super-cache.0.9.9.9.zip -d $WP_CACHE_PATH 80 | chown -R www-data.www-data $WP_CACHE_PATH 81 | mv $WP_CACHE_PATH/wp-super-cache/wp-cache-config-sample.php $WP_CACHE_PATH/wp-super-cache/wp-cache-config.php 82 | } 83 | 84 | function setup_initial_wp_cache_configuration { 85 | cat << 'EOF' >>../wp-cache-config.php 86 | $wp_cache_mobile_groups = ''; 87 | $wp_cache_mobile_prefixes = 'w3c , w3c-, acs-, alav, alca, amoi, audi, avan, benq, bird, blac, blaz, brew, cell, cldc, cmd-, dang, doco, eric, hipt, htc_, inno, ipaq, ipod, jigs, kddi, keji, leno, lg-c, lg-d, lg-g, lge-, lg/u, maui, maxo, midp, mits, mmef, mobi, mot-, moto, mwbp, nec-, newt, noki, palm, pana, pant, phil, play, port, prox, qwap, sage, sams, sany, sch-, sec-, send, seri, sgh-, shar, sie-, siem, smal, smar, sony, sph-, symb, t-mo, teli, tim-, tosh, tsm-, upg1, upsi, vk-v, voda, wap-, wapa, wapi, wapp, wapr, webc, winw, winw, xda , xda-'; 88 | $wp_cache_refresh_single_only = '0'; 89 | $wp_cache_mod_rewrite = 0; 90 | $wp_cache_front_page_checks = 0; 91 | $wp_supercache_304 = 0; 92 | $wp_cache_slash_check = 0; 93 | $cache_enabled = true; 94 | $super_cache_enabled = true; 95 | $sem_id = 1816471371; 96 | $wp_cache_mobile_enabled = 1; 97 | EOF 98 | } 99 | 100 | function activate_wp_cache_plugin { 101 | #$1 - MySQL user 102 | #$2 - MySQL password 103 | #$3 - Wordpress Database name 104 | echo "UPDATE wp_options SET option_value='/index.php/archives/%post_id%' WHERE option_name='permalink_structure';" | mysql --user="$1" --password="$2" $3 105 | echo "UPDATE wp_options SET option_value='a:1:{i:0;s:27:\"wp-super-cache/wp-cache.php\";}' WHERE option_name='active_plugins';" | mysql --user="$1'" --password="$2" $3 106 | echo "UPDATE wp_options SET autoload='yes' WHERE option_name='active_plugins';" | mysql --user="$1" --password="$2" $3 107 | } 108 | -------------------------------------------------------------------------------- /lib/git.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################## 4 | # Git / Gitolite # 5 | ################## 6 | 7 | function git_install 8 | { 9 | aptitude install -y git-core 10 | aptitude install -y git 11 | } 12 | 13 | function gitolite_install 14 | { 15 | aptitude install -y ssh 16 | git_install 17 | if [ ! -d "/srv/git" ] ; then 18 | 19 | #make sure root has a pubkey 20 | if [ ! -e /root/.ssh/id_rsa ] ; then 21 | rm -rf /root/.ssh/gitolite_admin_id_rsa* 22 | printf "/root/.ssh/gitolite_admin_id_rsa\n\n\n\n\n" | ssh-keygen -t rsa -P "" 23 | 24 | #give root gitolite admin priviledges 25 | ln -s /root/.ssh/gitolite_admin_id_rsa /root/.ssh/id_rsa 26 | ln -s /root/.ssh/gitolite_admin_id_rsa.pub /root/.ssh/id_rsa.pub 27 | fi 28 | 29 | #create git user 30 | adduser \ 31 | --system \ 32 | --shell /bin/sh \ 33 | --gecos 'git version control' \ 34 | --ingroup www-data \ 35 | --disabled-password \ 36 | --home /srv/git \ 37 | git 38 | if [ ! -d /srv/git ] ; then 39 | mkdir -p /srv/git 40 | chown git:www-data /srv/git 41 | fi 42 | 43 | #install gitolite 44 | local curdir=$(pwd) 45 | cp /root/.ssh/gitolite_admin_id_rsa.pub /tmp/gitolite_admin_id_rsa.pub 46 | cd /tmp 47 | git clone git://github.com/sitaramc/gitolite.git 48 | cd gitolite 49 | git checkout "v2.0" 50 | mkdir -p /usr/local/share/gitolite/conf /usr/local/share/gitolite/hooks /srv/git/repositories 51 | src/gl-system-install /usr/local/bin /usr/local/share/gitolite/conf /usr/local/share/gitolite/hooks 52 | chown -R git:www-data /srv/git 53 | su git -c "gl-setup -q /tmp/gitolite_admin_id_rsa.pub" 54 | 55 | #remove testing repo 56 | cd /tmp 57 | cat << 'EOF' > "/tmp/git_env_ssh" 58 | #!/bin/bash 59 | exec ssh -o stricthostkeychecking=no -i /root/.ssh/gitolite_admin_id_rsa "$@" 60 | EOF 61 | chmod 700 "/tmp/git_env_ssh" 62 | rm -rf gitolite-admin 63 | env GIT_SSH="/tmp/git_env_ssh" git clone git@localhost:gitolite-admin.git 64 | cd gitolite-admin 65 | local testing_line=$(cat conf/gitolite.conf | grep -n "repo.*testing" | sed 's/:.*$//g') 66 | if [ -n "$testing_line" ] ; then 67 | head -n $(( $testing_line - 1 )) conf/gitolite.conf > conf/gitolite.tmp 68 | mv conf/gitolite.tmp conf/gitolite.conf 69 | git commit -a -m "add project $PROJ_ID" 70 | env GIT_SSH="/tmp/git_env_ssh" git push 71 | fi 72 | rm -rf /srv/git/repositories/testing.git 73 | cd /tmp 74 | rm -rf /tmp/git_env_ssh 75 | rm -rf gitolite-admin 76 | 77 | 78 | #install git daemon 79 | #(only exports public projects, with git-daemon-export-ok file, so by default it is secure) 80 | cat << 'EOF' > /etc/init.d/git-daemon 81 | #!/bin/sh 82 | 83 | test -f /usr/lib/git-core/git-daemon || exit 0 84 | 85 | . /lib/lsb/init-functions 86 | 87 | GITDAEMON_OPTIONS="--reuseaddr --verbose --base-path=/srv/git/repositories/ --detach" 88 | 89 | case "$1" in 90 | start) log_daemon_msg "Starting git-daemon" 91 | 92 | start-stop-daemon --start -c git:www-data --quiet --background \ 93 | --exec /usr/lib/git-core/git-daemon -- ${GITDAEMON_OPTIONS} 94 | 95 | log_end_msg $? 96 | ;; 97 | stop) log_daemon_msg "Stopping git-daemon" 98 | 99 | start-stop-daemon --stop --quiet --name git-daemon 100 | 101 | log_end_msg $? 102 | ;; 103 | *) log_action_msg "Usage: /etc/init.d/git-daemon {start|stop}" 104 | exit 2 105 | ;; 106 | esac 107 | exit 0 108 | EOF 109 | chmod 755 "/etc/init.d/git-daemon" 110 | update-rc.d git-daemon defaults 111 | /etc/init.d/git-daemon start 112 | 113 | cd "$curdir" 114 | 115 | fi 116 | } 117 | 118 | function create_git 119 | { 120 | local PROJ_ID=$1 ; shift ; 121 | local PROJ_IS_PUBLIC=$1 ; shift ; 122 | 123 | #optional -- only if we need to set up a post-recieve chiliproject hook 124 | local CHILI_INSTALL_PATH=$1 ; shift ; 125 | 126 | local curdir=$(pwd) 127 | 128 | #does nothing if git/gitolite is already installed 129 | git_install 130 | gitolite_install 131 | 132 | #create git repository 133 | cd /tmp 134 | cat << 'EOF' > "/tmp/git_env_ssh" 135 | #!/bin/bash 136 | exec ssh -o stricthostkeychecking=no -i /root/.ssh/gitolite_admin_id_rsa "$@" 137 | EOF 138 | chmod 700 "/tmp/git_env_ssh" 139 | rm -rf gitolite-admin 140 | env GIT_SSH="/tmp/git_env_ssh" git clone git@localhost:gitolite-admin.git 141 | cd gitolite-admin 142 | echo "" >>conf/gitolite.conf 143 | echo "repo $PROJ_ID" >>conf/gitolite.conf 144 | echo " RW+ = gitolite_admin_id_rsa" >>conf/gitolite.conf 145 | if [ -n "$PROJ_IS_PUBLIC" ] ; then 146 | echo " R = daemon" >>conf/gitolite.conf 147 | fi 148 | git commit -a -m "add project $PROJ_ID" 149 | env GIT_SSH="/tmp/git_env_ssh" git push 150 | cd /tmp 151 | rm -rf gitolite-admin 152 | rm -rf "/tmp/git_env_ssh" 153 | 154 | if [ -n "$CHILI_INSTALL_PATH" ] ; then 155 | #post-receive hook 156 | pr_file="/srv/git/repositories/$PROJ_ID.git/hooks/post-receive" 157 | cat << EOF > "$pr_file" 158 | #!/bin/sh 159 | 160 | sudo -u www-data ruby "$CHILI_INSTALL_PATH/script/runner" -e production "GitHosting::run_post_receive_hook(\"$PROJ_ID\")" >/dev/null 2>&1 161 | 162 | EOF 163 | chmod 700 "$pr_file" 164 | chown git:www-data "$pr_file" 165 | fi 166 | 167 | cd "$curdir" 168 | } 169 | -------------------------------------------------------------------------------- /lib/mysql.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ########################################################### 4 | # mysql-server 5 | ########################################################### 6 | 7 | function install_mysql { 8 | # $1 - the mysql root password 9 | 10 | log "Installing MySQL..." 11 | if [ ! -n "$1" ]; then 12 | log "mysql_install() requires the root password as its first argument" 13 | return 1; 14 | fi 15 | 16 | echo "mysql-server-5.1 mysql-server/root_password password $1" | debconf-set-selections 17 | echo "mysql-server-5.1 mysql-server/root_password_again password $1" | debconf-set-selections 18 | aptitude install -y mysql-server mysql-client libmysqld-dev libmysqlclient-dev 19 | 20 | echo "Sleeping while MySQL starts up for the first time..." 21 | sleep 5 22 | } 23 | 24 | function tune_mysql { 25 | # Tunes MySQL's memory usage to utilize the percentage of memory you specify, defaulting to 40% 26 | # $1 - the percent of system memory to allocate towards MySQL 27 | 28 | log "Tunning MySQL up..." 29 | if [ ! -n "$1" ]; 30 | then PERCENT=40 31 | else PERCENT="$1" 32 | fi 33 | 34 | sed -i -e 's/^#skip-innodb/skip-innodb/' /etc/mysql/my.cnf # disable innodb - saves about 100M 35 | 36 | MEM=$(awk '/MemTotal/ {print int($2/1024)}' /proc/meminfo) # how much memory in MB this system has 37 | MYMEM=$((MEM*PERCENT/100)) # how much memory we'd like to tune mysql with 38 | MYMEMCHUNKS=$((MYMEM/4)) # how many 4MB chunks we have to play with 39 | 40 | # mysql config options we want to set to the percentages in the second list, respectively 41 | OPTLIST=(key_buffer sort_buffer_size read_buffer_size read_rnd_buffer_size myisam_sort_buffer_size query_cache_size) 42 | DISTLIST=(75 1 1 1 5 15) 43 | for opt in ${OPTLIST[@]}; do 44 | sed -i -e "/\[mysqld\]/,/\[.*\]/s/^$opt/#$opt/" /etc/mysql/my.cnf 45 | done 46 | for i in ${!OPTLIST[*]}; do 47 | val=$(echo | awk "{print int((${DISTLIST[$i]} * $MYMEMCHUNKS/100))*4}") 48 | if [ $val -lt 4 ] 49 | then val=4 50 | fi 51 | config="${config}\n${OPTLIST[$i]} = ${val}M" 52 | done 53 | sed -i -e "s/\(\[mysqld\]\)/\1\n$config\n/" /etc/mysql/my.cnf 54 | /etc/init.d/mysql restart 55 | } 56 | 57 | function create_mysql_database { 58 | # $1 - the mysql root password 59 | # $2 - the db name to create 60 | if [ ! -n "$1" ]; then 61 | log "mysql_create_database() requires the root pass as its first argument" 62 | return 1; 63 | fi 64 | if [ ! -n "$2" ]; then 65 | log "mysql_create_database() requires the name of the database as the second argument" 66 | return 1; 67 | fi 68 | log "Creating database $2..." 69 | echo "CREATE DATABASE $2;" | mysql -u root -p$1 70 | } 71 | 72 | function create_mysql_user { 73 | # $1 - the mysql root password 74 | # $2 - the user to create 75 | # $3 - their password 76 | if [ ! -n "$1" ]; then 77 | log "mysql_create_user() requires the root pass as its first argument" 78 | return 1; 79 | fi 80 | if [ ! -n "$2" ]; then 81 | log "mysql_create_user() requires username as the second argument" 82 | return 1; 83 | fi 84 | if [ ! -n "$3" ]; then 85 | log "mysql_create_user() requires a password as the third argument" 86 | return 1; 87 | fi 88 | log "Creating MySQL user $2..." 89 | echo "CREATE USER '$2'@'localhost' IDENTIFIED BY '$3';" | mysql -u root -p$1 90 | } 91 | 92 | function grant_mysql_user { 93 | # $1 - the mysql root password 94 | # $2 - the user to bestow privileges 95 | # $3 - the database 96 | if [ ! -n "$1" ]; then 97 | log "mysql_grant_user() requires the root pass as its first argument" 98 | return 1; 99 | fi 100 | if [ ! -n "$2" ]; then 101 | log "mysql_grant_user() requires username as the second argument" 102 | return 1; 103 | fi 104 | if [ ! -n "$3" ]; then 105 | log "mysql_grant_user() requires a database as the third argument" 106 | return 1; 107 | fi 108 | log "Granting MySQL user $2 all privileges to $3 database..." 109 | echo "GRANT ALL PRIVILEGES ON $3.* TO '$2'@'localhost';" | mysql -u root -p$1 110 | echo "FLUSH PRIVILEGES;" | mysql -u root -p$1 111 | } 112 | 113 | function backup_mysql 114 | { 115 | if [ ! -n "$1" ]; then 116 | log "backup_mysql() requires the database user as its first argument" 117 | return 1; 118 | fi 119 | if [ ! -n "$2" ]; then 120 | log "backup_mysql) requires the database password as its second argument" 121 | return 1; 122 | fi 123 | if [ ! -n "$3" ]; then 124 | log "backup_mysql() requires the output file path as its third argument" 125 | return 1; 126 | fi 127 | local USER="$1" 128 | local PASS="$2" 129 | local BACKUP_DIR="$3" 130 | local DBNAMES="$4" 131 | 132 | fname="" 133 | if [ -n "$DBNAMES" ] ; then 134 | fname=$(echo "$DBNAMES" | sed 's/ /_/g') 135 | mysqldump --single-transaction --add-drop-table --add-drop-database -h localhost --user="$USER" --password="$PASS" --databases $DBNAMES > "/tmp/$fname-db.sql" 136 | else 137 | fname="all" 138 | mysqldump --single-transaction --add-drop-table --add-drop-database -h localhost --user="$USER" --password="$PASS" --all-databases > "/tmp/$fname-db.sql" 139 | fi 140 | 141 | mkdir -p "$BACKUP_DIR" 142 | local curdir=$(pwd) 143 | cd /tmp 144 | rm -rf "$BACKUP_DIR/$fname-db.tar.bz2" 145 | tar cjf "$BACKUP_DIR/$fname-db.tar.bz2" "$fname-db.sql" 146 | rm -rf "$fname-db.sql" 147 | cd "$curdir" 148 | } 149 | 150 | function restore_mysql 151 | { 152 | if [ ! -n "$1" ]; then 153 | log "restore_mysql() requires the database user as its first argument" 154 | return 1; 155 | fi 156 | if [ ! -n "$2" ]; then 157 | log "restore_mysql) requires the database password as its second argument" 158 | return 1; 159 | fi 160 | if [ ! -n "$3" ]; then 161 | log "restore_mysql() requires the backup directory as its third argument" 162 | return 1; 163 | fi 164 | 165 | local USER="$1" 166 | local DB_PASSWORD="$2" 167 | local BACKUP_DIR="$3" 168 | 169 | rm -rf "/tmp/tmp.db" "/tmp/tmp.db.all.sql" 170 | mkdir "/tmp/tmp.db" 171 | 172 | db_zips=$(ls "$BACKUP_DIR/"*-db.tar.bz2) 173 | for dbz in $db_zips ; do 174 | tar -C "/tmp/tmp.db" -xjf "$dbz" 175 | cat /tmp/tmp.db/* >> "/tmp/tmp.db.all.sql" 176 | rm -rf /tmp/tmp.db/* 177 | done 178 | 179 | #ensure that current user (usually root) and debian-sys-maint have same password as before, and that they still have all permissions 180 | old_debian_pw=$(echo $(cat /etc/mysql/debian.cnf | grep password | sed 's/^.*=[\t ]*//g') | awk ' { print $1 } ') 181 | echo "USE mysql ;" >> "/tmp/tmp.db.all.sql" 182 | echo "GRANT ALL ON *.* TO 'debian-sys-maint'@'localhost' ;" >> "/tmp/tmp.db.all.sql" 183 | echo "GRANT ALL ON *.* TO '$USER'@'localhost' ;" >> "/tmp/tmp.db.all.sql" 184 | echo "UPDATE user SET password=PASSWORD(\"$old_debian_pw\") WHERE User='debian-sys-maint' ;" >> "/tmp/tmp.db.all.sql" 185 | echo "UPDATE user SET password=PASSWORD(\"$DB_PASSWORD\") WHERE User='$USER' ;" >> "/tmp/tmp.db.all.sql" 186 | echo "FLUSH PRIVILEGES ;" >> "/tmp/tmp.db.all.sql" 187 | 188 | mysql --user="$USER" --password="$DB_PASSWORD" < "/tmp/tmp.db.all.sql" 189 | rm -rf "/tmp/tmp.db" "/tmp/tmp.db.all.sql" 190 | 191 | touch /tmp/restart-mysql 192 | } 193 | -------------------------------------------------------------------------------- /lib/utils.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ########################################################### 4 | # utilitary functions 5 | ########################################################### 6 | 7 | function log { 8 | if [ ! -n "$1" ]; then 9 | log "log() requires text string as its argument" 10 | return 1; 11 | fi 12 | echo "`date '+%D %T'` - $1" 13 | } 14 | 15 | function ask { 16 | if [ ! -n "$1" ]; then 17 | log "ask() requires a question to ask" 18 | return 1; 19 | fi 20 | read -p "$1 " ANSWER 21 | echo "$ANSWER" 22 | } 23 | 24 | function upgrade_system { 25 | log "Upgrading System..." 26 | apt-get update 27 | apt-get -y install aptitude 28 | aptitude -y full-upgrade 29 | } 30 | 31 | install_essentials() { 32 | log "Installing Essentials..." 33 | aptitude -y install build-essential zlib1g-dev libpcre3-dev libssl-dev libcurl4-openssl-dev libreadline5-dev libreadline6-dev libreadline-dev libxml2-dev libxslt1-dev libmysqlclient-dev openssh-server git-core wget vim less bash-completion curl rsync locate imagemagick libyaml-dev libffi-dev 34 | } 35 | 36 | enable_root_color_prompt() { 37 | sed -i -e 's/^#PS1=/PS1=/' /root/.bashrc 38 | } 39 | 40 | function lower { 41 | echo $1 | tr '[:upper:]' '[:lower:]' 42 | } 43 | 44 | function update_locale_en_US_UTF_8 { 45 | log "Updating locale to en_US.UTF-8..." 46 | dpkg-reconfigure locales 47 | update-locale LANG=en_US.UTF-8 48 | } 49 | 50 | better_bash_prompt() 51 | { 52 | local USE_DETAILED=$1 53 | 54 | for bashfile in /root/.bashrc /etc/skel/.bashrc ; do 55 | cat <<'EOF' >$bashfile 56 | 57 | # ~/.bashrc: executed by bash(1) for non-login shells. 58 | # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) 59 | # for examples 60 | 61 | # If not running interactively, don't do anything 62 | [ -z "$PS1" ] && return 63 | 64 | # don't put duplicate lines in the history. See bash(1) for more options 65 | #export HISTCONTROL=ignoredups 66 | 67 | # check the window size after each command and, if necessary, 68 | # update the values of LINES and COLUMNS. 69 | shopt -s checkwinsize 70 | 71 | # make less more friendly for non-text input files, see lesspipe(1) 72 | [ -x /usr/bin/lesspipe ] && eval "$(lesspipe)" 73 | 74 | # set variable identifying the chroot you work in (used in the prompt below) 75 | if [ -z "$debian_chroot" -a -r /etc/debian_chroot ]; then 76 | debian_chroot=$(cat /etc/debian_chroot) 77 | fi 78 | 79 | 80 | 81 | # enable color support of ls and also add handy aliases 82 | if [ "$TERM" != "dumb" ]; then 83 | 84 | color_test=$(ls --color 3>&1 2>&1 >/dev/null) 85 | eval "`dircolors -b 2>/dev/null`" 86 | 87 | if [ -z "$color_test" ] ; then 88 | #no errors, alias to ls --color 89 | eval "`dircolors -b`" 90 | alias ls='ls --color=auto' 91 | alias dir='ls --color=auto --format=vertical' 92 | alias vdir='ls --color=auto --format=long' 93 | 94 | else 95 | #--color flag doesn't work, use -G (we're probably on OSX) 96 | alias ls='ls -G' 97 | fi 98 | fi 99 | 100 | # some more ls aliases 101 | alias ll='ls -al' 102 | #alias la='ls -A' 103 | #alias l='ls -CF' 104 | 105 | # enable programmable completion features (you don't need to enable 106 | # this, if it's already enabled in /etc/bash.bashrc and /etc/profile 107 | # sources /etc/bash.bashrc). 108 | #if [ -f /etc/bash_completion ]; then 109 | # . /etc/bash_completion 110 | #fi 111 | 112 | 113 | # Alias definitions. 114 | # You may want to put all your additions into a separate file like 115 | # ~/.bash_aliases, instead of adding them here directly. 116 | # See /usr/share/doc/bash-doc/examples in the bash-doc package. 117 | 118 | #if [ -f ~/.bash_aliases ]; then 119 | # . ~/.bash_aliases 120 | #fi 121 | 122 | 123 | 124 | # git is a bitch -- it pipes the output of git diff into less 125 | # unless PAGER variable is set to cat. Shouldn't cat be 126 | # the default??? WHAT. THE. HELL. 127 | PAGER=cat 128 | export PAGER 129 | 130 | 131 | 132 | color_red='\[\033[01;31m\]' 133 | color_orange='\[\033[00;33m\]' 134 | color_green='\[\033[00;32m\]' 135 | color_blue='\[\033[01;34m\]' 136 | color_purple='\[\033[01;35m\]' 137 | color_cyan='\[\033[01;36m\]' 138 | color_white='\[\033[01;37m\]' 139 | color_default='\[\033[00m\]' 140 | 141 | root=$(groups | egrep "root") 142 | admin=$(groups | egrep "wheel|admin") 143 | color_user=$color_green 144 | if [ -n "$root" ] ; then 145 | color_user=$color_red 146 | elif [ -n "$admin" ] ; then 147 | color_user=$color_orange 148 | fi 149 | 150 | ######################################################################## 151 | # VCS part mostly shamelessly ripped off from acdha's bash prompt: # 152 | # http://github.com/acdha/unix_tools/blob/master/etc/bash_profile # 153 | ######################################################################## 154 | 155 | # Utility function so we can test for things like .git/.hg without firing 156 | # up a separate process 157 | 158 | __git_branch() 159 | { 160 | local g="$(git rev-parse --git-dir 2>/dev/null)" 161 | if [ -n "$g" ]; then 162 | local r 163 | local b 164 | if [ -d "$g/../.dotest" ] 165 | then 166 | r="|AM/REBASE" 167 | b="$(git symbolic-ref HEAD 2>/dev/null)" 168 | elif [ -f "$g/.dotest-merge/interactive" ] 169 | then 170 | r="|REBASE-i" 171 | b="$(cat $g/.dotest-merge/head-name)" 172 | elif [ -d "$g/.dotest-merge" ] 173 | then 174 | r="|REBASE-m" 175 | b="$(cat $g/.dotest-merge/head-name)" 176 | elif [ -f "$g/MERGE_HEAD" ] 177 | then 178 | r="|MERGING" 179 | b="$(git symbolic-ref HEAD 2>/dev/null)" 180 | else 181 | if [ -f $g/BISECT_LOG ] 182 | then 183 | r="|BISECTING" 184 | fi 185 | if ! b="$(git symbolic-ref HEAD 2>/dev/null)" 186 | then 187 | b="$(cut -c1-7 $g/HEAD)..." 188 | fi 189 | fi 190 | if [ -n "$1" ]; then 191 | printf "$1" "${b##refs/heads/}$r" 192 | else 193 | printf "%s" "${b##refs/heads/}$r" 194 | fi 195 | fi 196 | } 197 | __vcs_prompt_part() 198 | { 199 | name="" 200 | local git_branch=$(__git_branch) 201 | local hg_branch=$(hg branch 2>/dev/null) 202 | if [ -d .svn ] ; then 203 | name="svn" ; 204 | elif [ -d RCS ] ; then 205 | echo "RCS" ; 206 | elif [ -n "$git_branch" ] ; then 207 | name="git, $git_branch" ; 208 | elif [ -n "$hg_branch" ] ; then 209 | name="hg, $hg_branch" 210 | else 211 | name="" 212 | fi 213 | if [ -n "$name" ] ; then 214 | echo -e '-(\033[01;35m'$name'\033[00m)' #purple 215 | else 216 | echo "" 217 | fi 218 | } 219 | 220 | 221 | detailed='${debian_chroot:+($debian_chroot)}'$color_default'\n('$color_user'\u@\h'$color_default')-('$color_cyan'\d \@'$color_default')$(__vcs_prompt_part)\n'$color_default'('$color_blue'\w'$color_default')\$ ' 222 | short='${debian_chroot:+($debian_chroot)}'$color_user'\u@\h'$color_default':'$color_blue'\w'$color_default'$ ' 223 | 224 | PS1=$short 225 | 226 | EOF 227 | 228 | if [ "$USE_DETAILED" = "1" ] ; then 229 | sed -i -e 's/^PS1=\$short[\t ]*$/PS1=$detailed/' $bashfile 230 | fi 231 | done 232 | } 233 | 234 | function better_stuff 235 | { 236 | aptitude install -y unzip wget vim less imagemagick sudo whois dnsutils 237 | better_bash_prompt 238 | } 239 | -------------------------------------------------------------------------------- /lib/nginx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################# 4 | # nginx # 5 | ################################# 6 | 7 | function install_nginx { 8 | log "Installing nginx..." 9 | aptitude install -y nginx 10 | } 11 | 12 | function create_nginx_wordpress_site { 13 | #$1 - server name 14 | log "Creating nginx config file for wordpress site $1..." 15 | cat > /etc/nginx/sites-available/wordpress << EOF 16 | server { 17 | listen 8080; 18 | server_name $1; 19 | root /var/www/wordpress; 20 | 21 | index index.php; 22 | 23 | access_log /var/log/nginx/$1-access_log; 24 | error_log /var/log/nginx/$1-error_log; 25 | 26 | location / { 27 | try_files \$uri \$uri/ /index.php?\$args; 28 | } 29 | 30 | location ~ \.php$ { 31 | try_files \$uri =404; 32 | fastcgi_index index.php; 33 | fastcgi_pass php5-fpm-sock; 34 | fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name; 35 | include /etc/nginx/fastcgi_params; 36 | } 37 | 38 | rewrite ^.*/files/(.*)$ /wp-includes/ms-files.php?file=\$1 last; 39 | if (!-e \$request_filename) { 40 | rewrite ^(.+)$ /index.php?q=\$1 last; 41 | } 42 | } 43 | EOF 44 | } 45 | 46 | function nginx_create_site 47 | { 48 | local server_id="$1" 49 | local server_name_list="$2" 50 | local is_ssl="$3" 51 | local rails_paths="$4" 52 | local enable_php="$5" 53 | local enable_perl="$6" 54 | 55 | port="80" 56 | ssl_cert="" 57 | ssl_ckey="" 58 | ssl="" 59 | if [ "$is_ssl" = "1" ] ; then 60 | port="443" 61 | ssl="ssl on;" 62 | ssl_cert="ssl_certificate $NGINX_CONF_PATH/ssl/nginx.pem;" 63 | ssl_ckey="ssl_certificate_key $NGINX_CONF_PATH/ssl/nginx.key;" 64 | if [ ! -e "$NGINX_CONF_PATH/ssl/nginx.pem" ] || [ ! -e "$NGINX_CONF_PATH/ssl/nginx.key" ] ; then 65 | aptitude install -y ssl-cert 66 | mkdir -p "$NGINX_CONF_PATH/ssl" 67 | make-ssl-cert generate-default-snakeoil --force-overwrite 68 | cp /etc/ssl/certs/ssl-cert-snakeoil.pem "$NGINX_CONF_PATH/ssl/nginx.pem" 69 | cp /etc/ssl/private/ssl-cert-snakeoil.key "$NGINX_CONF_PATH/ssl/nginx.key" 70 | fi 71 | fi 72 | 73 | config_path="$NGINX_CONF_PATH/sites-available/$server_id" 74 | cat << EOF >"$config_path" 75 | server 76 | { 77 | listen $port; 78 | server_name $server_name_list; 79 | access_log $NGINX_PREFIX/$server_id/logs/access.log; 80 | root $NGINX_PREFIX/$server_id/public_html; 81 | index index.html index.htm index.php index.cgi; 82 | $ssl 83 | $ssl_cert 84 | $ssl_ckey 85 | 86 | error_page 400 406 407 409 410 411 412 413 414 415 416 417 418 422 423 424 425 426 444 449 450 490 /error/400.html; 87 | error_page 401 /error/401.html; 88 | error_page 402 /error/402.html; 89 | error_page 403 /error/403.html; 90 | error_page 404 /error/404.html; 91 | error_page 405 /error/405.html; 92 | error_page 408 /error/408.html; 93 | 94 | error_page 500 506 507 509 510 /error/500.html; 95 | error_page 501 /error/501.html; 96 | error_page 502 /error/502.html; 97 | error_page 503 /error/503.html; 98 | error_page 504 /error/504.html; 99 | error_page 505 /error/505.html; 100 | 101 | location = /error/403.html 102 | { 103 | allow all; 104 | } 105 | 106 | #rails 107 | EOF 108 | 109 | if [ -z "$rails_paths" ] ; then 110 | cat << EOF >>"$config_path" 111 | #passenger_enabled on; 112 | #passenger_base_uri rails_app; ##should be symlink to public dir of actual rails_app 113 | EOF 114 | else 115 | echo ' passenger_enabled on;' >>"$config_path" 116 | if [ "$rails_paths" != '.' ] ; then 117 | for rp in $rails_paths ; do 118 | echo " passenger_base_uri $rp; " >> "$config_path" 119 | done 120 | fi 121 | fi 122 | 123 | local php_comment="" 124 | local perl_comment="" 125 | if [ "$enable_php" == '0' ] ; then 126 | php_comment="#" 127 | fi 128 | if [ "$enable_perl" == '0' ] ; then 129 | perl_comment="#" 130 | fi 131 | 132 | cat << EOF >>"$config_path" 133 | 134 | ${php_comment}#php 135 | ${php_comment}location ~ \.php\$ 136 | ${php_comment}{ 137 | ${php_comment} try_files \$uri =404; 138 | ${php_comment} fastcgi_pass unix:/var/run/php-fpm.sock ; 139 | ${php_comment} include $NGINX_CONF_PATH/fastcgi_params; 140 | ${php_comment}} 141 | 142 | ${perl_comment}#perl 143 | ${perl_comment}location ~ \.pl\$ 144 | ${perl_comment}{ 145 | ${perl_comment} fastcgi_pass unix:/var/run/fcgiwrap.socket ; 146 | ${perl_comment} include $NGINX_CONF_PATH/fastcgi_params; 147 | ${perl_comment}} 148 | 149 | EOF 150 | 151 | echo "}" >> "$config_path" 152 | 153 | mkdir -p "$NGINX_PREFIX/$server_id/logs" 154 | cp -r "$YOURCHILI_INSTALL_DIR/default_html" "$NGINX_PREFIX/$server_id/public_html" 155 | cat "$YOURCHILI_INSTALL_DIR/default_html/index.html" | sed "s/SERVER_ID/$server_id/g" > "$NGINX_PREFIX/$server_id/public_html/index.html" 156 | chown -R www-data:www-data "$NGINX_PREFIX/$server_id" 157 | 158 | } 159 | 160 | function enable_nginx_site { 161 | #$1 - site name 162 | log "Enabling nginx site $1..." 163 | ln -s "/etc/nginx/sites-available/$1" "/etc/nginx/sites-enabled/$1" 164 | /etc/init.d/nginx restart 165 | } 166 | 167 | function disable_nginx_site 168 | { 169 | #$1 - site name 170 | rm -rf "/etc/nginx/sites-enabled/$1" 171 | /etc/init.d/nginx restart 172 | } 173 | 174 | function nginx_delete_site 175 | { 176 | #$1 - site name 177 | rm -rf "/etc/nginx/sites-enabled/$1" 178 | rm -rf "/etc/nginx/sites-available/$1" 179 | /etc/init.d/nginx restart 180 | } 181 | 182 | function nginx_add_passenger_uri_for_vhost 183 | { 184 | local VHOST_CONFIG_FILE=$1 185 | local URI=$2 186 | 187 | escaped_uri=$(escape_path "$URI" ) 188 | 189 | NL=$'\\\n' 190 | TAB=$'\\\t' 191 | cat "$VHOST_CONFIG_FILE" | grep -v -P "^[\t ]*passenger_base_uri[\t ]+$escaped_search_uri;" > "$VHOST_CONFIG_FILE.tmp" 192 | enabled_line=$(grep -P "^[\t #]*passenger_enabled[\t ]+" "$VHOST_CONFIG_FILE") 193 | if [ -n "$enabled_line" ] ; then 194 | cat "$VHOST_CONFIG_FILE.tmp" | sed -e "s/^.*passenger_enabled.*$/${TAB}passenger_enabled on;${NL}${TAB}passenger_base_uri $escaped_uri;/g" > "$VHOST_CONFIG_FILE" 195 | else 196 | cat "$VHOST_CONFIG_FILE.tmp" | sed -e "s/^{$/{${NL}${TAB}passenger_enabled on;${NL}${TAB}passenger_base_uri $escaped_uri;/g" > "$VHOST_CONFIG_FILE" 197 | fi 198 | rm -rf "$VHOST_CONFIG_FILE.tmp" 199 | } 200 | 201 | function nginx_add_include_for_vhost 202 | { 203 | local VHOST_CONFIG_FILE=$1 204 | local INCLUDE_FILE=$2 205 | 206 | escaped_search_include=$(escape_path "$INCLUDE_FILE" ) 207 | 208 | cat "$VHOST_CONFIG_FILE" | grep -v -P "^[\t ]*include[\t ]+$escaped_search_include;" | grep -v "^}[\t ]*$" > "$VHOST_CONFIG_FILE.tmp" 209 | printf "\tinclude $INCLUDE_FILE;\n" >>"$VHOST_CONFIG_FILE.tmp" 210 | echo "}" >>"$VHOST_CONFIG_FILE.tmp" 211 | mv "$VHOST_CONFIG_FILE.tmp" "$VHOST_CONFIG_FILE" 212 | } 213 | 214 | function nginx_set_rails_as_vhost_root 215 | { 216 | local VHOST=$1 ; shift 217 | local RAILS_PATH=$1 ; shift 218 | 219 | local vhost_config="/etc/nginx/sites-available/$VHOST" 220 | local rails_public_path="$RAILS_PATH/public" 221 | rails_public_path=$(echo "$rails_public_path" | sed 's/public\/public$/public/g') 222 | 223 | local rails_public_escaped_path=$(escape_path "$rails_public_path" ) 224 | 225 | #note: invoking perl like this is like sed, but better, cuz' it handles tabs properly 226 | perl -pi -e 's/^[\t ]*passenger_base_uri[\t ]+.*$//g' $vhost_config 227 | perl -pi -e 's/^.*passenger_enabled[\t ]+.*$/\tpassenger_enabled on;/g' $vhost_config 228 | perl -pi -e "s/[\t ]*root[\t ]+.*$/\troot $rails_public_escaped_path;/g" $vhost_config 229 | } 230 | 231 | function install_nginx_compiling 232 | { 233 | if [ ! -n "$1" ]; then 234 | echo "nginx_install requires server user as its first argument" 235 | return 1; 236 | fi 237 | if [ ! -n "$2" ]; then 238 | echo "nginx_install requires server group as its second argument" 239 | return 1; 240 | fi 241 | 242 | local NGINX_USER="$1" 243 | local NGINX_GROUP="$2" 244 | local NGINX_USE_PHP="$3" 245 | local NGINX_USE_PASSENGER="$4" 246 | local NGINX_USE_PERL="$5" 247 | local NGINX_SERVER_STRING="$6" 248 | 249 | if [ -z "$NGINX_USE_PHP" ] ; then 250 | NGINX_USE_PHP=1 251 | fi 252 | if [ -z "$NGINX_USE_PASSENGER" ] ; then 253 | NGINX_USE_PASSENGER=1 254 | fi 255 | if [ -z "$NGINX_SERVER_STRING" ] ; then 256 | NGINX_SERVER_STRING=$(randomString 25) 257 | fi 258 | 259 | if [ "$NGINX_USE_PHP" = 1 ] ; then 260 | php_fpm_install "$NGINX_USER" "$NGINX_GROUP" 261 | fi 262 | if [ "$NGINX_USE_PASSENGER" = 1 ] ; then 263 | ruby_install 264 | fi 265 | if [ "$NGINX_USE_PERL" = 1 ] ; then 266 | perl_fcgi_install 267 | fi 268 | 269 | local curdir=$(pwd) 270 | 271 | #theres a couple dependencies. 272 | aptitude install -y libpcre3-dev libcurl4-openssl-dev libssl-dev 273 | 274 | #not nginx specific deps 275 | aptitude install -y wget build-essential 276 | 277 | #need dpkg-dev for no headaches when apt-get source nginx 278 | aptitude install -y dpkg-dev 279 | 280 | #directory to play in 281 | mkdir /tmp/nginx 282 | cd /tmp/nginx 283 | 284 | #grab and extract 285 | wget "http://nginx.org/download/nginx-$NGINX_VER.tar.gz" 286 | tar -xzvf "nginx-$NGINX_VER.tar.gz" 287 | 288 | #Camouflage NGINX Server Version String.... 289 | perl -pi -e "s/\"Server:.*CRLF/\"Server: $NGINX_SERVER_STRING\" CRLF/g" "nginx-$NGINX_VER/src/http/ngx_http_header_filter_module.c" 290 | perl -pi -e "s/\"Server:[\t ]+nginx\"/\"Server: $NGINX_SERVER_STRING\"/g" "nginx-$NGINX_VER/src/http/ngx_http_header_filter_module.c" 291 | 292 | #Don't inform user of what server is running when responding with an error code 293 | perl -pi -e "s/\\.*<\/center\>/
Server Response<\/center>/g" "nginx-$NGINX_VER/src/http/ngx_http_special_response.c" 294 | 295 | #maek eet 296 | cd "nginx-$NGINX_VER" 297 | 298 | nginx_conf_file="$NGINX_CONF_PATH/nginx.conf" 299 | nginx_http_log_file="$NGINX_HTTP_LOG_PATH/access.log" 300 | 301 | passenger_root="" 302 | passenger_path="" 303 | if [ "$NGINX_USE_PASSENGER" = 1 ] ; then 304 | passenger_root=`$RUBY_PREFIX/bin/passenger-config --root` 305 | passenger_path="$passenger_root/ext/nginx" 306 | 307 | #bugfix for passenger 3.0.9, otherwise it won't compile 308 | is_309=$(echo "$passenger_path" | grep "3\.0\.9") 309 | if [ -n "$is_309" ] ; then 310 | if [ -e "$passenger_path/ContentHandler.c" ] ; then 311 | sed -i 's/^.*[* \t]main_conf[ \t;].*$//g' "$passenger_path/ContentHandler.c" 312 | fi 313 | if [ -e "$passenger_path/config" ] ; then 314 | cat << 'EOF' >>$passenger_path/config 315 | 316 | ngx_feature="Math library" 317 | ngx_feature_name= 318 | ngx_feature_run=no 319 | ngx_feature_incs="#include " 320 | ngx_feature_path= 321 | ngx_feature_libs="-lm" 322 | ngx_feature_test="pow(1, 2)" 323 | . auto/feature 324 | if [ $ngx_found = yes ]; then 325 | CORE_LIBS="$CORE_LIBS -lm" 326 | fi 327 | 328 | EOF 329 | fi 330 | echo "" 331 | echo "PATCHING BUGS IN PASSENGER 3.0.9" 332 | echo "" 333 | fi 334 | 335 | ./configure --prefix="$NGINX_PREFIX" --sbin-path="$NGINX_SBIN_PATH" --conf-path="$nginx_conf_file" --pid-path="$NGINX_PID_PATH" --error-log-path="$NGINX_ERROR_LOG_PATH" --http-log-path="$nginx_http_log_file" --user="$NGINX_USER" --group="$NGINX_GROUP" --with-http_ssl_module --with-debug --add-module="$passenger_path" 336 | else 337 | ./configure --prefix="$NGINX_PREFIX" --sbin-path="$NGINX_SBIN_PATH" --conf-path="$nginx_conf_file" --pid-path="$NGINX_PID_PATH" --error-log-path="$NGINX_ERROR_LOG_PATH" --http-log-path="$nginx_http_log_file" --user="$NGINX_USER" --group="$NGINX_GROUP" --with-http_ssl_module --with-debug 338 | fi 339 | 340 | make 341 | make install 342 | 343 | #grab source for ready-made scripts 344 | apt-get source nginx 345 | 346 | #alter init to match sbin path specified in configure. add to init.d 347 | sed -i "s@DAEMON=/usr/sbin/nginx@DAEMON=$NGINX_SBIN_PATH@" nginx-*/debian/*init.d 348 | cp nginx-*/debian/*init.d /etc/init.d/nginx 349 | chmod 744 /etc/init.d/nginx 350 | update-rc.d nginx defaults 351 | 352 | #use provided logrotate file. adjust as you please 353 | sed -i "s/daily/$LOGRO_FREQ/" nginx-*/debian/*logrotate 354 | sed -i "s/52/$LOGRO_ROTA/" nginx-*/debian/*logrotate 355 | cp nginx*/debian/*logrotate /etc/logrotate.d/nginx 356 | 357 | pass_comment="" 358 | if [ "$NGINX_USE_PASSENGER" != 1 ] ; then 359 | pass_comment="#" 360 | fi 361 | 362 | #setup default nginx config files 363 | echo "fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;" >> "$NGINX_CONF_PATH/fastcgi_params"; 364 | cat <$NGINX_CONF_PATH/nginx.conf 365 | 366 | worker_processes 4; 367 | 368 | events 369 | { 370 | worker_connections 1024; 371 | } 372 | http 373 | { 374 | include mime.types; 375 | default_type application/octet-stream; 376 | 377 | server_names_hash_max_size 4096; 378 | server_names_hash_bucket_size 4096; 379 | 380 | ${pass_comment}passenger_root $passenger_root; 381 | ${pass_comment}passenger_ruby $RUBY_PREFIX/bin/ruby; 382 | ${pass_comment}passenger_max_pool_size 3; 383 | ${pass_comment}passenger_pool_idle_time 0; 384 | ${pass_comment}passenger_max_instances_per_app 3; 385 | 386 | 387 | #proxy settings (only relevant when nginx used as a proxy) 388 | proxy_set_header Host \$host; 389 | proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; 390 | proxy_set_header X-Real-IP \$remote_addr; 391 | 392 | 393 | keepalive_timeout 65; 394 | sendfile on; 395 | 396 | #gzip on; 397 | #tcp_nopush on; 398 | 399 | include $NGINX_CONF_PATH/sites-enabled/*; 400 | } 401 | EOF 402 | 403 | mkdir -p "$NGINX_CONF_PATH/sites-enabled" 404 | mkdir -p "$NGINX_CONF_PATH/sites-available" 405 | 406 | #create default site & start nginx 407 | nginx_create_site "default" "localhost" "0" "" "$NGINX_USE_PHP" "$NGINX_USE_PERL" 408 | nginx_create_site "$NGINX_SSL_ID" "localhost" "1" "" "$NGINX_USE_PHP" "$NGINX_USE_PERL" 409 | 410 | nginx_ensite "default" 411 | nginx_ensite "$NGINX_SSL_ID" 412 | 413 | #delete build directory 414 | chown -R www-data:www-data /srv/www 415 | 416 | #return to original directory 417 | cd "$curdir" 418 | } 419 | 420 | function get_root_for_site_id 421 | { 422 | VHOST_ID=$1 423 | echo $(cat "/etc/nginx/sites-available/$VHOST_ID" | grep -P "^[\t ]*root" | awk ' { print $2 } ' | sed 's/;.*$//g') 424 | } 425 | 426 | function get_domain_for_site_id 427 | { 428 | echo $(cat "/etc/nginx/sites-available/$1" | grep server_name | sed 's/;//g' | awk ' {print $2} ') 429 | } 430 | 431 | ################################################################################# 432 | # Utility function for generating SSL key & certificate signing request (.csr) # 433 | # Useful if you need authenticated HTTPS # 434 | # key and csr files are generated in current working directory # 435 | # old key and csr files are removed # 436 | ################################################################################# 437 | 438 | function gen_ssl_key_and_request 439 | { 440 | local country="$1" # 2 letter code, e.g. "US" 441 | local state="$2" # Full name of state/province, e.g. "Rhode Island" 442 | local city="$3" # Full city name, e.g. "Providence" 443 | local organization="$4" # Your full organization name, e.g. "Diane's Dildo Emporium LLC" 444 | local org_unit="$5" # Organizational unit, can be blank e.g. "Web Services" 445 | local site_name="$6" # Full domain name e.g. "www.dianesdildos.com" 446 | local email="$7" # Contact email address e.g. "dirtydiane@dianesdildos.com" 447 | local valid_time="$8" # Number of days cert will be valid e.g. "365" (for one year) 448 | 449 | rm -rf "$site_name.key" "$site_name.csr" 450 | printf "$country\n$state\n$city\n$organization\n$org_unit\n$site_name\n$email\n\n\n\n\n\n" | openssl req -new -days "$valid_time" -nodes -newkey rsa:2048 -keyout "$site_name.key" -out "$site_name.csr" 451 | } 452 | --------------------------------------------------------------------------------