Template userdata script for setting up Amazon Machine Images (AMI)
#!/bin/bash
username="centos"
us_east_2_efs_logs="fs-xxxxxxx1"
us_east_2_efs_conf="fs-xxxxxxx2"
us_west_2_efs_logs="fs-xxxxxxx3"
us_west_2_efs_conf="fs-xxxxxxx4"
swap_gb_size=2
yum_update() {
yum update -y
}
install_eple_and_ius_repo() {
yum install -y \
https://repo.ius.io/ius-release-el7.rpm \
https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
}
install_base_packages() {
install_eple_and_ius_repo
yum groupinstall -y 'Development Tools'
yum install -y wget screen tree vim-enhanced unzip jq git setroubleshoot
yum install -y htop nmon nc lsof tcpdump mtr bind-utils openssl python36u
}
install_amazon_efs_utils() {
# Based on: https://docs.aws.amazon.com/efs/latest/ug/using-amazon-efs-utils.html#installing-other-distro
yum install -y git make rpm-build
cd /opt/
git clone https://github.com/aws/efs-utils
cd efs-utils
git pull
make rpm
yum -y install ./build/amazon-efs-utils*rpm
}
install_awscli() {
cd /tmp
curl "https://s3.amazonaws.com/aws-cli/awscli-bundle.zip" -o "awscli-bundle.zip"
unzip -o awscli-bundle.zip
./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws
}
install_aws_ssm_agent() {
yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
systemctl disable amazon-ssm-agent
}
install_httpd() {
cd /etc/yum.repos.d
wget https://repo.codeit.guru/codeit.el`rpm -q --qf "%{VERSION}" $(rpm -q --whatprovides redhat-release)`.repo
yum install -y httpd mod_ssl python2-certbot-apache
config_httpd
systemctl enable httpd
}
config_httpd() {
cp -a /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.orig
echo "IncludeOptional sites-enabled/*.conf" >> /etc/httpd/conf/httpd.conf
mkdir -p /etc/httpd/sites-{available,enabled}
mv /etc/httpd/conf.d/autoindex.conf /etc/httpd/sites-available/
mv /etc/httpd/conf.d/userdir.conf /etc/httpd/sites-available/
mv /etc/httpd/conf.d/welcome.conf /etc/httpd/sites-available/
config_httpd_selinux
systemctl restart httpd
}
config_httpd_selinux() {
setsebool -P httpd_use_nfs 1
getsebool httpd_use_nfs
setsebool -P httpd_can_network_connect 1
getsebool httpd_can_network_connect
}
install_openjdk8() {
yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel
ln -sf /etc/alternatives/jre_openjdk /usr/lib/jvm/jdk8
}
install_nvm_node_yarn_pm2() {
runuser -l ${username} -c 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.0/install.sh | bash'
curl --silent --location https://rpm.nodesource.com/setup_12.x | bash -
curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | tee /etc/yum.repos.d/yarn.repo
yum install -y yarn
npm install -g pm2
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u ${username} --hp /home/${username}
}
set_timezone_to_pacific() {
timedatectl set-timezone America/Los_Angeles
}
config_bash() {
echo 'if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
PATH=/usr/local/bin:$PATH:$HOME/.local/bin:$HOME/bin
export PATH
' >> /root/.bashrc
echo 'if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
' | tee -a /root/.bashrc >> /home/${username}/.bashrc
echo "
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias ll='ls -al'
alias la='ls -A'
alias lla='ls -alFA'
alias l='ls -CF'
alias ds='ls -latr'
alias cls='clear'
alias sudo='sudo '
alias vi='vim'
alias v='vim -u NONE -N'
" | tee -a /root/.bash_aliases >> /home/${username}/.bash_aliases
chown ${username}:${username} /home/${username}/.bash_aliases
}
config_vim() {
yum install -y git
runuser -l ${username} -c 'mkdir -p ~/.vim/{autoload,bundle}'
runuser -l ${username} -c 'curl -LSso ~/.vim/autoload/pathogen.vim https://raw.githubusercontent.com/tpope/vim-pathogen/master/autoload/pathogen.vim'
runuser -l ${username} -c 'cd ~/.vim/bundle; git clone --depth=1 https://github.com/bling/vim-airline.git'
runuser -l ${username} -c 'cd ~/.vim/bundle; git clone --depth=1 https://github.com/tpope/vim-repeat.git'
runuser -l ${username} -c 'cd ~/.vim/bundle; git clone --depth=1 https://github.com/tpope/vim-eunuch.git'
runuser -l ${username} -c 'cd ~/.vim/bundle; git clone --depth=1 https://github.com/tpope/vim-endwise.git'
runuser -l ${username} -c 'cd ~/.vim/bundle; git clone --depth=1 https://github.com/tpope/vim-surround.git'
runuser -l ${username} -c 'cd ~/.vim/bundle; git clone --depth=1 https://github.com/tpope/vim-unimpaired.git'
runuser -l ${username} -c 'cd ~/.vim/bundle; git clone --depth=1 https://github.com/tpope/vim-commentary.git'
runuser -l ${username} -c 'cd ~/.vim/bundle; git clone --depth=1 https://github.com/scrooloose/syntastic.git'
echo '
execute pathogen#infect()
execute pathogen#helptags()
syntax on
filetype plugin indent on
set nocompatible
set history=700
set syntax=on
set autoread
set hlsearch
set showmatch
set cursorline
set scrolloff=999
set ruler
set wildmenu
set laststatus=2
set wildmode=list:longest
set expandtab
set smarttab
set shiftwidth=4
set tabstop=4
set wildmenu
set wildmode=list:longest,list:full
set wildignore+=*/tmp/*,*.swp,*.pyc,*.class
set visualbell
set hidden
set switchbuf=useopen
let mapleader = ","
let g:mapleader = ","
nmap <silent> <leader>d "_d
map <silent> <leader>d "_d
map <leader>/ :setlocal hlsearch!<CR>:set hlsearch?<CR>
map <leader>c :setlocal noignorecase!<CR>:set noignorecase?<CR>
noremap <leader>q :bp <BAR> bd #<CR>
nnoremap <C-h> "ryiw:%s/<C-r>r//gc<Left><Left><Left>
vnoremap <C-h> "ryiw:%s/<C-r>r//gc<Left><Left><Left>
" auto toggle paste
let &t_SI .= "\<Esc>[?2004h"
let &t_EI .= "\<Esc>[?2004l"
inoremap <special> <expr> <Esc>[200~ XTermPasteBegin()
function! XTermPasteBegin()
set pastetoggle=<Esc>[201~
set paste
return ""
endfunction
let g:airline#extensions#branch#enabled = 1
let g:airline#extensions#tabline#enabled = 1
let g:airline#extensions#syntastic#enabled = 1
set statusline+=%#warningmsg#
set statusline+=%{SyntasticStatuslineFlag()}
set statusline+=%*
let g:syntastic_always_populate_loc_list = 1
let g:syntastic_auto_loc_list = 1
let g:syntastic_check_on_open = 1
let g:syntastic_check_on_wq = 0
' >> /home/${username}/.vimrc
chown ${username}:${username} /home/${username}/.vimrc
ln -sf /home/${username}/.vimrc /root/.vimrc
ln -sf /home/${username}/.vim /root/.vim
}
config_screen() {
echo '
altscreen on
termcapinfo xterm * ti @: te @
defbce on
term xterm-256color
defscrollback 30000
hardstatus alwayslastline "%{= kc}%H (load: %l) %-21<%=%D %Y-%m-%d %02c:%s"
' > /home/${username}/.screenrc
chown ${username}:${username} /home/${username}/.screenrc
}
config_ulimit() {
echo "root soft nofile 4096" >> /etc/security/limits.conf
echo "root hard nofile 10240" >> /etc/security/limits.conf
echo "${username} soft nofile 4096" >> /etc/security/limits.conf
echo "${username} hard nofile 10240" >> /etc/security/limits.conf
}
config_chronyd() {
# CentOS comes with chronyd instead of ntp. See /etc/chrony.conf
if ! grep -q '^server 169.254.169.123' /etc/chrony.conf 2>/dev/null; then
sed -i '1s|^|server 169.254.169.123 prefer iburst minpoll 4 maxpoll 4\n|' \
/etc/chrony.conf
fi
}
mount_efs_volumes() {
setsebool -P logrotate_use_nfs 1
getsebool logrotate_use_nfs
region=$(curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region)
mkdir -p /mnt/efs/{logs,conf}
if [[ ${region} == "us-east-2" ]]; then
echo "${us_east_2_efs_logs}:/ /mnt/efs/logs efs defaults,_netdev 0 0
${us_east_2_efs_conf}:/ /mnt/efs/conf efs defaults,_netdev 0 0" >> /etc/fstab
mount -t efs ${us_east_2_efs_logs}:/ /mnt/efs/logs
mount -t efs ${us_east_2_efs_conf}:/ /mnt/efs/conf
fi
if [[ ${region} == "us-west-2" ]]; then
echo "${us_west_2_efs_logs}:/ /mnt/efs/logs efs defaults,_netdev 0 0
${us_west_2_efs_conf}:/ /mnt/efs/conf efs defaults,_netdev 0 0" >> /etc/fstab
mount -t efs ${us_west_2_efs_logs}:/ /mnt/efs/logs
mount -t efs ${us_west_2_efs_conf}:/ /mnt/efs/conf
fi
}
add_swap_partition() {
fallocate -l ${swap_gb_size}G /swap.1
dd if=/dev/zero of=/swap.1 bs=1M count=$((1024 * ${swap_gb_size}))
chmod 600 /swap.1
mkswap /swap.1
swapon /swap.1
echo "/swap.1 swap swap defaults 0 0" >> /etc/fstab
echo "vm.swappiness = 10" >> /etc/sysctl.conf
echo "vm.vfs_cache_pressure = 50" >> /etc/sysctl.conf
echo "net.core.netdev_max_backlog = 30000" >> /etc/sysctl.conf
echo "net.ipv4.tcp_max_syn_backlog = 8096" >> /etc/sysctlconf
echo "net.core.rmem_max = 134217728" >> /etc/sysctl.conf
echo "net.core.wmem_max = 134217728" >> /etc/sysctl.conf
echo "net.ipv4.tcp_rmem = 4096 87380 67108864" >> /etc/sysctl.conf
echo "net.ipv4.tcp_wmem = 4096 87380 67108864" >> /etc/sysctl.conf
}
### main ###
log_file=/var/log/ec2-userdata.log
# All output to one file and to the screen
exec > >(tee ${log_file}) 2>&1
start_time=$(date +%s)
set -x
date "+%F %H:%M:%S %z"
set_timezone_to_pacific
date "+%F %H:%M:%S %z"
yum_update
install_base_packages
install_amazon_efs_utils
install_awscli
install_aws_ssm_agent
install_httpd
install_openjdk8
install_nvm_node_yarn_pm2
config_bash
config_vim
config_screen
config_ulimit
config_chronyd
mount_efs_volumes
add_swap_partition
set +x
end_time=$(date +%s)
echo "$(date "+%F %H:%M:%S %z") Done. Time taken: $((${end_time} - ${start_time})) seconds"
# reboot for timezone, fstab and other changes
reboot