Skip to content

Instantly share code, notes, and snippets.

@zipizap
Last active September 6, 2016 09:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zipizap/75e77af2cbe3aec5b271589b9c3d1105 to your computer and use it in GitHub Desktop.
Save zipizap/75e77af2cbe3aec5b271589b9c3d1105 to your computer and use it in GitHub Desktop.
server script to create a new project, with its own user/group, gitolite-repo, rvm+ruby/gemset, etc
#!/bin/bash
function shw_grey { echo -e '\033[1;30m'"$1"'\033[0m'; }
function shw_norm { echo "$1"; }
function shw_info { echo -e '\033[1;34m'"$1"'\033[0m'; }
function shw_warn { echo -e '\033[1;33m'"$1"'\033[0m'; }
function shw_err { echo -e '\033[1;31mERROR: '"$1"'\033[0m'; exit 255; }
function run_as_user_new_proj { sudo -u $NEW_PROJ -i bash -l -c "$1" ; }
#exit if user is not zipizap
[ "$(whoami)" != "zipizap" ] && { echo "Must be run as user zipizap! Aborting"; exit 1;}
shw_info "Usage:"
shw_info " #Run as user zipizap "
shw_info " $0 <new-user>"
shw_info ""
shw_info "Example:"
shw_info " #creates user/git-repo/rvm-gemset/first-commit for "xmpp_send""
shw_info " $0 xmpp_send"
shw_info " "
shw_info "Description: "
shw_info " Must be run as user zipizap, to have:"
shw_info " - sudo without asking for password"
shw_info " - /home/zipizap/gitolite-admin, to configure gitolite"
shw_info ""
shw_info " This will automate the following sections of the file [1]: "
shw_info " 2. Preparing a server daemon-style user ("raven") for running a service"
shw_info " .Create user as a daemon-style user"
shw_info " .Create new repo in gitolite, for the service"
shw_info " .Inaugurate repo, and clone to user "raven""
shw_info " .Setup independent user-only rvm:ruby/gemsets, install specific ruby version, create gemset (ruby-1.9.3-p362@raven) and leave project .rvmrc and Gemfile in repo"
shw_info ""
shw_info ""
shw_info "Refs: "
shw_info "[1]: file:///home/zipizap/Dropbox/projs/vps_lnx/daemon_user.howto.md.html"
shw_info " "
# check args
[ "$1" ] || shw_err "Bad arguments! Aborting!"
NEW_PROJ=$1
#2. Preparing a server daemon-style user ("raven") for running a service"
# Create user as a daemon-style user
#---
# As root:
shw_info "Creating user"
sudo adduser --gecos "" --disabled-login $NEW_PROJ
[ $? -ne 0 ] && shw_err "something did not go well..."
# Created user will have:
# + HOME dir
# + only associated with 1 group: "the_user"
# + logins disabled both by password and by ssh-keys
# + normal shell, with environment setted by "~/.bashrc"
# To run a daemon with this user in /etc/init.d, you will have to:
# - manually recreate the daemon environment in /etc/default/my_daemon_environment.sh (see notes above including the stack overflow info: http://tinyurl.com/bdoc3kw )
# - create the /etc/init.d/my_daemon.sh script, containing in the start of the file a line like `. /etc/default/my_daemon_environment.sh`
#
# To "login" use: sudo su - <the_user>
#---
shw_info "Creating repo in gitolite-admin"
# Create new repo in gitolite, for the service
#as user zipizap
#update gitolite-admin in zipizap's-home
cd ~/gitolite-admin && git pull
[ $? -ne 0 ] && shw_err "something did not go well..."
#create ssh-keys for user $NEW_PROJ and copy pub-key to /home/zipizap/gitolite-admin/keydir/"$NEW_PROJ"_$(hostname).pub
__KEY_PRIV_PATH="/home/$NEW_PROJ/.ssh/id_rsa"
__KEY_PUB_PATH="/home/$NEW_PROJ/.ssh/id_rsa.pub"
NEW_PROJ_PUBKEY_NAME="$NEW_PROJ"_$(hostname)
__KEY_PUB_PATH_TMP="/tmp/"$NEW_PROJ_PUBKEY_NAME".pub"
run_as_user_new_proj "ssh-keygen -t rsa -N '' -f $__KEY_PRIV_PATH && cp -fv $__KEY_PUB_PATH $__KEY_PUB_PATH_TMP && chmod 666 $__KEY_PUB_PATH_TMP"
[ $? -ne 0 ] && shw_err "something did not go well..."
cp $__KEY_PUB_PATH_TMP $HOME/gitolite-admin/keydir
[ $? -ne 0 ] && shw_err "something did not go well..."
run_as_user_new_proj "rm -f $__KEY_PUB_PATH_TMP"
[ $? -ne 0 ] && shw_err "something did not go well..."
#gitolite.conf: add new repo and new user
GITOLITE_CONF_FILE="$HOME/gitolite-admin/conf/gitolite.conf"
#check repo does not yet exist (it should not!)
grep "repo $NEW_PROJ" $GITOLITE_CONF_FILE && shw_err "a repo named $NEW_PROJ already exists! aborting!"
cat >> $GITOLITE_CONF_FILE <<EOT
repo $NEW_PROJ
RW+ = @zipizaps
RW+ = $NEW_PROJ_PUBKEY_NAME
EOT
#git add && commit on gitolite-admin
cd $HOME/gitolite-admin && git add . && git commit -m "[auto] added new repo and user $NEW_PROJ" && git push
[ $? -ne 0 ] && shw_err "something did not go well..."
shw_info "Inaugurating repo and cloning into user home"
# Inaugurate repo, and clone to user "raven"
# Inaugurate empty repo:
# (run this as a dev-user with W permitions to the repo)
#hack to avoid first-time-host-key-checking which would prompt user interactively - this will accept by default new host keys without prompting
run_as_user_new_proj "echo -e 'Host 127.0.0.1\n StrictHostKeyChecking no\n' >> /home/$NEW_PROJ/.ssh/config"
[ $? -ne 0 ] && shw_err "something did not go well..."
#define git identity
run_as_user_new_proj "git config --global user.email '"$NEW_PROJ"_$(hostname)@localhost' && git config --global user.name '"$NEW_PROJ"_$(hostname)'"
[ $? -ne 0 ] && shw_err "something did not go well..."
run_as_user_new_proj "cd /home/$NEW_PROJ && git clone git@127.0.0.1:$NEW_PROJ" # clone repo
[ $? -ne 0 ] && shw_err "something did not go well...1"
run_as_user_new_proj "cd /home/$NEW_PROJ/$NEW_PROJ && touch .gitignore" # make first repo change
[ $? -ne 0 ] && shw_err "something did not go well...2"
run_as_user_new_proj "cd /home/$NEW_PROJ/$NEW_PROJ && git add . && git commit -m '[auto] first commit' && git push -u origin master" # commit && push -u origin master
[ $? -ne 0 ] && shw_err "something did not go well...3"
# see http://stackoverflow.com/a/6547682/259192
shw_info "Setting up RVM"
# Setup independent user-only rvm:ruby/gemsets, install specific ruby version, create gemset (ruby-1.9.3-p362@raven) and leave project .rvmrc and Gemfile in repo
#ruby/gemset .rvmrc
RUBY_VERSION_TO_USE="ruby" #used to install ruby and to name gemset
MODEL_IRBRC="/usr/local/rvm/rubies/default/.irbrc"
shw_info " ~/.irbrc"
run_as_user_new_proj "cd && cp $MODEL_IRBRC ~/.irbrc && rvm user all"
[ $? -ne 0 ] && shw_err "something did not go well...4"
# Sometimes, there is a strange dir created: /home/$NEW_PROJ/1/ - this hack deletes it in case it appears
run_as_user_new_proj "[ -d '/home/$NEW_PROJ/1' ] && rmdir '/home/$NEW_PROJ/1'"
run_as_user_new_proj "rvm autolibs disable"
[ $? -ne 0 ] && shw_err "something did not go well...4a"
shw_info " ~/.gemrc"
run_as_user_new_proj "echo 'gem: --no-ri --no-rdoc' >> /home/$NEW_PROJ/.gemrc" #this skips rdoc and ri generation when installing gems
shw_info " Ruby $RUBY_VERSION_TO_USE"
run_as_user_new_proj "rvm install $RUBY_VERSION_TO_USE"
[ $? -ne 0 ] && shw_err "something did not go well...5"
shw_info " Gemset: $RUBY_VERSION_TO_USE@$NEW_PROJ"
run_as_user_new_proj "rvm use --create $RUBY_VERSION_TO_USE@$NEW_PROJ"
[ $? -ne 0 ] && shw_err "something did not go well...6"
shw_info " ~/.rvmrc"
run_as_user_new_proj "echo 'export rvm_trust_rvmrcs_flag=1' >> /home/$NEW_PROJ/.rvmrc" #this avoids prompts asking to trust project's .rvmrc - it will accept them by default
[ $? -ne 0 ] && shw_err "something did not go well...7"
shw_info " Set default ruby"
run_as_user_new_proj "cd && cd $NEW_PROJ && rvm use --rvmrc $RUBY_VERSION_TO_USE@$NEW_PROJ"
[ $? -ne 0 ] && shw_err "something did not go well...8"
# NOTE: Previously, this was failing because RVM was not updated... and some dependencies were missing. Now it works
#Project files
shw_info "Setting up project files"
#Gemfile
shw_info " Gemfile"
run_as_user_new_proj "echo -e 'source \"http://rubygems.org\"' > /home/$NEW_PROJ/$NEW_PROJ/Gemfile"
run_as_user_new_proj "echo -e '#-- Examples --' >> /home/$NEW_PROJ/$NEW_PROJ/Gemfile"
run_as_user_new_proj "echo -e '#gem \"nokogiri\", \"~> 1.5.6\"' >> /home/$NEW_PROJ/$NEW_PROJ/Gemfile"
run_as_user_new_proj "echo -e '#gem \"xmpp4r-simple\", \"~> 0.8.8\", :git => \"git://github.com/blaine/xmpp4r-simple.git\"' >> /home/$NEW_PROJ/$NEW_PROJ/Gemfile"
[ $? -ne 0 ] && shw_err "something did not go well...9"
#Readme.md.html
shw_info " Readme.md.html"
run_as_user_new_proj "wget https://raw.github.com/zipizap/strapdown_template/master/strapdown_template.md.html -qO /home/$NEW_PROJ/$NEW_PROJ/Readme.md.html"
[ $? -ne 0 ] && shw_err "something did not go well...10"
# $NEW_PROJ.rb (basic header with rvm + bundler wrappers)
shw_info " Skeleton .rb file"
run_as_user_new_proj "cd /home/$NEW_PROJ/$NEW_PROJ && "'echo -e "#\x21$HOME/.rvm/wrappers/$(basename $GEM_HOME)/ruby" >> $HOME/'"$NEW_PROJ/$NEW_PROJ.rb"
run_as_user_new_proj "echo 'ENV[\"BUNDLE_GEMFILE\"]=File.join(File.dirname(File.realpath(__FILE__)),\"Gemfile\") #fix to make bundle work when script is run from any location/user' >> /home/$NEW_PROJ/$NEW_PROJ/$NEW_PROJ.rb"
run_as_user_new_proj "echo '' >> /home/$NEW_PROJ/$NEW_PROJ/$NEW_PROJ.rb"
run_as_user_new_proj "echo '# -- Here require non-bundler gems' >> /home/$NEW_PROJ/$NEW_PROJ/$NEW_PROJ.rb"
run_as_user_new_proj "echo '#require \"pry\"' >> /home/$NEW_PROJ/$NEW_PROJ/$NEW_PROJ.rb"
run_as_user_new_proj "echo '' >> /home/$NEW_PROJ/$NEW_PROJ/$NEW_PROJ.rb"
run_as_user_new_proj "echo '# -- From this point onward, require only bundler-installed-gems (non-bundler gems not requirable anymore... its a bundler side-effect...)' >> /home/$NEW_PROJ/$NEW_PROJ/$NEW_PROJ.rb"
run_as_user_new_proj "echo 'require \"bundler/setup\"' >> /home/$NEW_PROJ/$NEW_PROJ/$NEW_PROJ.rb"
run_as_user_new_proj "echo -e '' >> /home/$NEW_PROJ/$NEW_PROJ/$NEW_PROJ.rb"
run_as_user_new_proj "chmod 750 /home/$NEW_PROJ /home/$NEW_PROJ/$NEW_PROJ /home/$NEW_PROJ/$NEW_PROJ/$NEW_PROJ.rb"
#git add & commit
shw_info " git add && commit"
run_as_user_new_proj "cd /home/$NEW_PROJ/$NEW_PROJ && git add . && git commit -m '[auto] added empty Gemfile, .rvmrc, Readme.md.html $NEW_PROJ.rb' && git push"
[ $? -ne 0 ] && shw_err "something did not go well...11"
# Install common gems, in the gemset (not in Gemfile/bundler)
shw_info "Installing common gems into gemset (maybe this should all be bundled some day...)"
GEMS_TO_INSTALL="awesome_print pry wirble"
run_as_user_new_proj "cd && cd $NEW_PROJ && gem install --no-rdoc $GEMS_TO_INSTALL"
#All done, exit
echo -e "\n\n"
shw_info "All done now - created:"
shw_info " . new user&group '$NEW_PROJ' (password&ssh-disabled, use 'sudo su - $NEW_PROJ')"
shw_info " . dirs '/home/$NEW_PROJ/$NEW_PROJ/' with 750, to allow members of group '$NEW_PROJ'"
shw_info " . new gitolite-repo '$NEW_PROJ' with standard permitions and initial commits"
shw_info " . user-only rvm + ruby/gemset (ruby-xxxlastxxx@$NEW_PROJ) + project .rvmrc "
shw_info " . installed common irb gems in gemset (just in gemset, not in Gemfile/bundler)"
shw_info " . Gemfile (empty with examples)"
shw_info " . Readme.md.html (empty)"
shw_info " . $NEW_PROJ.rb (sample executable ruby file, with rvm+bundle wrappers, ready to be used executed by members of group '$NEW_PROJ')"
shw_info " . final git structure: "
shw_info " /home/$NEW_PROJ/$NEW_PROJ/"
shw_info " ├── .gitignore "
shw_info " ├── .rvmrc # rvm ruby-1.9.3-pxxx@$NEW_PROJ"
shw_info " ├── Gemfile # gems for application (install gems with: bundle install)"
shw_info " ├── Readme.md.html # for your documentation"
shw_info " └── $NEW_PROJ.rb # sample executable ruby file (with rvm+bundle wrappers, ready to be used by members of group '$NEW_PROJ')"
shw_info ""
shw_info ""
shw_info "You may now like to see section '3. Preparing remote-dev environment and tools' of file:///C:/Users/zipizap/Documents/My%20Dropbox/projs/vps_lnx/daemon_user.howto.md.html"
shw_info "Copied bellow for your supreme comfort"
shw_info ""
shw_info ' 3. Preparing remote-dev environment and tools'
shw_info ' #############################################'
shw_info ' # How to setup dev environment from scratch #'
shw_info ' #############################################'
shw_info ' # # install git-core'
shw_info ' # sudo apt-get install git-core'
shw_info ' # # install rvm (see https://rvm.io/rvm/install/)'
shw_info ' # sudo apt-get install curl'
shw_info ' # \curl -L https://get.rvm.io | bash -s stable --ruby'
shw_info ' # # "git-enable" user'
shw_info ' # # in remote-dev pc:'
shw_info ' # . create rsa pub/priv keys'
shw_info ' # ssh-keygen -t rsa'
shw_info ' # . copy rsa pub key to server'
shw_info ' # scp ~/.ssh/id_rsa.pub server_user_that_configures_gitolite_admin@server.com:~/new_user_pub_key.pub'
shw_info ' # # in server, as server_user_that_configures_gitolite_admin:'
shw_info ' # . update gitolite-admin'
shw_info ' # cd gitolite-admin'
shw_info ' # git pull'
shw_info ' # . place remote-dev rsa pub key inside gitolite-admin repo'
shw_info ' # cp ~/new_user_pub_key.pub keydir/newUsername.pub'
shw_info ' # . edit conf/gitolite.conf to add newUsername permitions '
shw_info ' # vim conf/gitolite.conf # add user-permissions to a repo'
shw_info ' # . save config changes, by making a commit to gitolite-admin repo'
shw_info ' # git add . && git commit -m "added user: newUsername to repo: raven" && git push'
shw_info ' # . more info, see file://.../projs/vps_lnx/gitolite.md.html'
shw_info ' # # and go back to remote-dev pc'
shw_info ' # # clone repo'
shw_info ' # git clone git@vps3.no-ip.org:raven'
shw_info ' # git push -u origin master'
shw_info ' # # RVM: install specific ruby version as indicated in .rvmrc'
shw_info ' # cd raven && cat .rvmrc # see specific ruby version'
shw_info ' # rvm install 1.9.3 # install specific ruby version '
shw_info ' # # Note: gemset should have been automatically created by project .rvmrc'
shw_info ' # # sync gems with bundler'
shw_info ' # cd raven && gem install bundler && bundle install'
shw_info ' # '
shw_info ' # # And from now on, the remote-dev can enter the normal workflow:'
shw_info ' # .git fetch-or-pull'
shw_info ' # ....make changes...'
shw_info ' # .git add . && git commit -m "changes made" #multiple times...'
shw_info ' # .git push #at the end, push to server'
shw_info ' #'
shw_info ' #'
shw_info ' #'
shw_info ' # # Create local-branch, push to remote-branch, pull to another-dev local-branch'
shw_info ' ### DEV1 env'
shw_info ' # Create new local-branch: "my_branch_01"'
shw_info ' git checkout -b my_branch_01'
shw_info ' ...'
shw_info ' git add . && git commit -m "first commit of branch_01"'
shw_info ' '
shw_info ' # Push local-branch to (new) repo-remote-branch'
shw_info ' git push -u origin my_branch_01 '
shw_info ' '
shw_info ' '
shw_info ' ### DEV2 env (another-dev)'
shw_info ' # Pull remote-branch to another-dev (new) local-branch '
shw_info ' git pull && git checkout --track origin/my_branch_01'
shw_info ' #'
shw_info ' #'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment