Skip to content

Instantly share code, notes, and snippets.

@ossipov
Last active April 5, 2020 19:48
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 ossipov/7fd976ef92614fdf3da2d16b4c1c3ded to your computer and use it in GitHub Desktop.
Save ossipov/7fd976ef92614fdf3da2d16b4c1c3ded to your computer and use it in GitHub Desktop.
Initial settings for CentOS8 on a new VPS
#!/bin/bash
#
# CentOs 8 Initial Setup
# * by ossipov.me
#
# Secure server:
# - Superuser account with root access
# - Disable root access from Internet
# - Change SSHd default port number
# - www-data user for nginx
#
# Apps Installed:
# - Nginx (latest)
# - Php-fpm 7.3
# - MariaDB
# - Midnight Commander
# - Htop
# - Composer
# - Nano (keybord friendly mode)
# - Zsh (with default config for new users)
# - Git
# - NodeJS
# - Yarn
# - Java 8
# - PM2
# - Acme.sh
# - ElasticSearch
#
# Run on fresh CentOs 8 install:
# sh -c "$(curl -L bit.ly/centos8init)"
#
# Default params:
#
SSHD_PORT="2211"
NGINX_VERSION="$(curl -s https://nginx.org/en/download.html | grep -E '([0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2})' -o | head -1)"
clear
echo ""
echo " ----------------------------------------------------------- "
echo " > CentOS 8 Initial Setup script < "
echo " ----------------------------------------------------------- "
echo " this script is ment to be run on a clean CentOS 8 install "
echo " as a root user "
echo " ----------------------------------------------------------- "
echo ""
# Create new account
echo ""
echo " Root account would be disabled in sshd. "
echo " We'll create superuser with administrative rights. "
echo ""
read -p " Create new username: " USER_NAME
if [ "$USER_NAME" == "" ] ; then exit ; fi
echo ""
echo " ----------------------------------------------------------- "
# Ask for SSH-RSA public key
echo ""
echo " Generate key pair on Windows using ssh-keygen: "
echo " mkdir %userprofile%\.ssh\keys\vps "
echo " ssh-keygen -t rsa -N '' -f %userprofile%\.ssh\keys\vps\id_rsa "
echo ""
echo " Copy contens of \"%userprofile%\.ssh\keys\vps\id_rsa.pub\" "
echo " It should be a string like: "
echo " ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDRf9EO......Nd9= user@domain"
echo ""
read -p " and paste it here: " ID_RSA_PUB
if [ "$ID_RSA_PUB" == "" ] ; then exit ; fi
echo ""
echo " ----------------------------------------------------------- "
# Change SSHd default port
echo ""
echo " SSHd port would also be changed from :22 "
echo ""
read -p " Set SSHd port (defaults to - ${SSHD_PORT}):" answer
if [ "$answer" != "" ] ; then SSHD_PORT=${answer} ; fi
echo ""
echo " ----------------------------------------------------------- "
# Change NGINX default version
echo ""
read -p " NGINX version to install (defaults to - ${NGINX_VERSION}):" answer
if [ "$answer" != "" ] ; then NGINX_VERSION=${answer} ; fi
echo ""
echo " -----------------------------------------------------"
echo ""
echo " Username.........: " ${USER_NAME}
echo " NGINX version....: " ${NGINX_VERSION}
echo " SSHD port........: " ${SSHD_PORT}
echo ""
echo " --[ssh public key]-----------------------------------"
echo ${ID_RSA_PUB}
echo " -----------------------------------------------------"
echo ""
echo " Do you wish to continue?"
select yn in "Yes" "No"; do
case $yn in
Yes ) break;;
No ) exit;;
esac
done
# --------------------------------------------------------------------------------
# Let's go to root's home:
# --------------------------------------------------------------------------------
cd ~
# --------------------------------------------------------------------------------
# Set Hostname:
# --------------------------------------------------------------------------------
nmtui-hostname
# --------------------------------------------------------------------------------
# Install EPEL + REMI Repo
# --------------------------------------------------------------------------------
# dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
dnf install -y epel-release
dnf install -y http://rpms.remirepo.net/enterprise/remi-release-8.rpm
dnf config-manager --set-enabled PowerTools
dnf clean all
dnf update -y
# --------------------------------------------------------------------------------
# APPS
# --------------------------------------------------------------------------------
dnf install -y wget mc htop python3 git nano
dnf install -y policycoreutils-python-utils
dnf install -y lnav
cp /usr/share/mc/syntax/sh.syntax /usr/share/mc/syntax/unknown.syntax
git config --global core.autocrlf input
sh -c 'cat << EOF >> /etc/nanorc
set linenumbers
set morespace
set mouse
set nowrap
set smooth
set speller "hunspell"
set tabsize 2
set wordbounds
set titlecolor brightblack
set statuscolor brightwhite,green
set errorcolor brightwhite,red
set numbercolor black
set keycolor brightcyan
set functioncolor green
include "/usr/share/nano/*.nanorc"
bind ^c copytext main
bind ^x cut main
bind ^v uncut main
bind ^z undo main
bind ^y redo main
bind ^f whereis main
bind F1 help main
bind F2 savefile main
bind F3 findnext main
bind F10 exit main
bind ^h replace main
bind ^\ comment main
EOF'
# git config --global user.name "Server Joe"
# git config --global user.email johndoe@example.com
# --------------------------------------------------------------------------------
# NodeJS
# --------------------------------------------------------------------------------
dnf install -y nodejs
# --------------------------------------------------------------------------------
# Yarn
# --------------------------------------------------------------------------------
curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
sudo rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg
dnf install -y yarn
# --------------------------------------------------------------------------------
# PM2 # https://pm2.keymetrics.io/docs/usage/quick-start/
# --------------------------------------------------------------------------------
yarn global add pm2
# # stop and delete all previous pm2 processes for www user
# pm2 stop all || true
# pm2 delete all || true
# # remove startup script and kill any lingering pm2 processes
# pm2 unstartup || true
# pkill -f pm2 || true
# # start pm2 processes for the 'www' user
# pm2 start app_path
# # save process list and create startup script
# pm2 save
# pm2 startup -u root
# pm2 startup
# pm2 start app.js
# pm2 save
# pm2 resurrect
# pm2 monitor
# --------------------------------------------------------------------------------
# MariaDB
# --------------------------------------------------------------------------------
dnf module install -y mariadb
rpm -qi mariadb-server
systemctl enable --now mariadb
clear
mysql_secure_installation
# --------------------------------------------------------------------------------
# Zsh
# --------------------------------------------------------------------------------
pip3 install Pygments
dnf install -y zsh
ZSH="/usr/share/oh-my-zsh" RUNZSH="no" sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"
cd /usr/share/oh-my-zsh/
cp templates/zshrc.zsh-template zshrc
sed -i "/plugins=(/d" /usr/share/oh-my-zsh/zshrc
sed -i "/source /d" /usr/share/oh-my-zsh/zshrc
sed -i "/ZSH\s*=/d" /usr/share/oh-my-zsh/zshrc
sed -i "/ZSH_THEME\s*=/d" /usr/share/oh-my-zsh/zshrc
sh -c 'cat << EOF >> /usr/share/oh-my-zsh/zshrc
export ZSH=/usr/share/oh-my-zsh
export ZSH_CACHE_DIR=~/.oh-my-zsh/cache
export EDITOR=nano
plugins=(git zsh-syntax-highlighting colorize zsh-autosuggestions)
ZSH_THEME="agnoster"
DISABLE_MAGIC_FUNCTIONS="true"
DISABLE_AUTO_UPDATE="true"
alias zconf="nano ~/.zshrc"
alias c="clear"
source \$ZSH/oh-my-zsh.sh
EOF'
ln -f /usr/share/oh-my-zsh/zshrc /etc/skel/.zshrc
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git /usr/share/oh-my-zsh/plugins/zsh-syntax-highlighting
git clone https://github.com/zsh-users/zsh-autosuggestions /usr/share/oh-my-zsh/plugins/zsh-autosuggestions
sed -i "/SHELL\s*=/d" /etc/default/useradd
echo "SHELL=/usr/bin/zsh" >> /etc/default/useradd
for n in $(users); do usermod -s /usr/bin/zsh $n; sudo -u $n /bin/cp -rf /etc/skel/.zshrc /home/$n/.zshrc; sudo -u $n mkdir -p /home/$n/.oh-my-zsh/cache; done;
usermod -s /usr/bin/zsh root
cp -rf /etc/skel/.zshrc ~/.zshrc
mkdir -p ~/.oh-my-zsh/cache
# --------------------------------------------------------------------------------
# WWW-DATA user for NGINX
# --------------------------------------------------------------------------------
useradd -s /sbin/nologin -d /var/www -r -M -U -u 777 www-data
mkdir /var/www
mkdir -p /var/www/letsencrypt/.well-known/acme-challenge
chown -R www-data:www-data /var/www
find /var/www -type d -exec chmod 2775 {} +
find /var/www -type f -exec chmod 0664 {} +
usermod -aG www-data nginx
usermod -aG www-data mysql
id www-data && id nginx && id mysql
ls -la /var | grep www
sudo -u www-data ssh-keygen -t rsa -N '' -f /var/www/.ssh/id_rsa
# --------------------------------------------------------------------------------
# NGINX
# --------------------------------------------------------------------------------
dnf install -y gcc gcc-c++ make zlib-devel pcre-devel openssl-devel
dnf install -y gd-devel geoip-devel
wget https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz
tar -xzvf nginx-$NGINX_VERSION.tar.gz
cd nginx-$NGINX_VERSION
./configure \
--user=www-data \
--group=www-data \
--sbin-path=/usr/bin/nginx \
--prefix=/var/lib/nginx \
--modules-path=/etc/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--http-log-path=/var/log/nginx/access.log \
--error-log-path=/var/log/nginx/error.log \
--lock-path=/var/lock/nginx.lock \
--pid-path=/run/nginx.pid \
--http-client-body-temp-path=/var/lib/nginx/temp/body \
--http-fastcgi-temp-path=/var/lib/nginx/temp/fastcgi \
--http-proxy-temp-path=/var/lib/nginx/temp/proxy \
--http-scgi-temp-path=/var/lib/nginx/temp/scgi \
--http-uwsgi-temp-path=/var/lib/nginx/temp/uwsgi \
--with-compat \
--with-debug \
--with-pcre-jit \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-http_auth_request_module \
--with-http_v2_module \
--with-http_dav_module \
--with-http_slice_module \
--with-threads \
--with-http_addition_module \
--with-http_geoip_module=dynamic \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_image_filter_module=dynamic \
--with-http_sub_module \
--with-stream=dynamic \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-mail=dynamic \
--with-mail_ssl_module
make
make install
cd ..
rm -rf nginx-$NGINX_VERSION
sh -c 'cat << EOF >> /lib/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/bin/nginx -t
ExecStart=/usr/bin/nginx
ExecReload=/usr/bin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF'
mkdir -p /var/lib/nginx/temp/body
firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --permanent --zone=public --add-service=https
firewall-cmd --reload
firewall-cmd --list-all
#
# todo: Settings
#
systemctl start nginx.service
systemctl enable nginx.service
# --------------------------------------------------------------------------------
# PHP7.3
# --------------------------------------------------------------------------------
dnf module list | grep php
dnf install -y dnf-plugins-core
dnf config-manager --set-enabled remi
sudo dnf module install -y php:remi-7.3
sudo dnf update
php -v
dnf install -y php-fpm php-mysqlnd php-zip php-gd php-mcrypt php-mbstring php-curl php-xml php-pear php-bcmath php-json
dnf install -y ImageMagick
dnf install -y php-imagick
systemctl enable --now php-fpm
# --------------------------------------------------------------------------------
# ACME.SH # https://github.com/Neilpang/acme.sh
# --------------------------------------------------------------------------------
curl https://get.acme.sh | sh
# acme.sh --install-cert -d example.com \
# --key-file /etc/nginx/ssl/example.com/key \
# --fullchain-file /etc/nginx/ssl/example.com/fullchain \
# --reloadcmd "service nginx force-reload"
# --------------------------------------------------------------------------------
# --------------------------------------------------------------------------------
# JAVA 8
# --------------------------------------------------------------------------------
dnf install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel
cat <<EOF | tee /etc/profile.d/java8.sh
export JAVA_HOME=/usr/lib/jvm/jre-openjdk
export PATH=\$PATH:\$JAVA_HOME/bin
export CLASSPATH=.:\$JAVA_HOME/jre/lib:\$JAVA_HOME/lib:\$JAVA_HOME/lib/tools.jar
EOF
source /etc/profile.d/java8.sh
# --------------------------------------------------------------------------------
# ELASTICSEARCH 6.7.2
# --------------------------------------------------------------------------------
# wget https://download.elasticsearch.org/elasticsearch/release/org/elasticsearch/distribution/rpm/elasticsearch/6.7.2/elasticsearch-6.7.2.rpm
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.7.2.rpm
sudo rpm --install elasticsearch-6.7.2.rpm
systemctl daemon-reload
service elasticsearch start
systemctl enable elasticsearch.service
systemctl start elasticsearch.service
# curl 127.0.0.1:9200
# --------------------------------------------------------------------------------
# COMPOSER
# --------------------------------------------------------------------------------
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php --install-dir=/bin --filename=composer
rm -f composer-setup.php
# --------------------------------------------------------------------------------
# SELinux settings
# --------------------------------------------------------------------------------
# If anything goes wrong, run:
# audit2why < /var/log/audit/audit.log
#
setsebool -P httpd_unified 1
setsebool -P httpd_can_network_connect 1
setsebool -P nis_enabled 1
setsebool -P httpd_can_network_connect_db=1
setsebool -P httpd_can_network_memcache=1
setsebool -P httpd_can_network_relay=1
setsebool -P httpd_can_sendmail=1
setsebool -P httpd_enable_cgi=1
setsebool -P httpd_enable_homedirs=1
semanage fcontext -a -t httpd_sys_rw_content_t "/var/www(/.*)?/public(/.*)?"
semanage fcontext -a -t httpd_sys_rw_content_t "/var/www(/.*)?/static(/.*)?"
semanage fcontext -a -t git_content_t "/var/www(/.*)?/.git(/.*)?"
grep denied /var/log/audit/audit.log | grep git | audit2allow -M git_allow
# --------------------------------------------------------------------------------
# Add New User:
# --------------------------------------------------------------------------------
useradd ${USER_NAME}
passwd ${USER_NAME}
usermod -aG wheel ${USER_NAME}
sudo -u ${USER_NAME} mkdir /home/${USER_NAME}/.ssh
sudo -u ${USER_NAME} touch /home/${USER_NAME}/.ssh/authorized_keys
sudo -u ${USER_NAME} echo ${ID_RSA_PUB} >> /home/${USER_NAME}/.ssh/authorized_keys
sudo -u ${USER_NAME} chmod 755 /home/${USER_NAME}/.ssh
sudo -u ${USER_NAME} chmod 600 /home/${USER_NAME}/.ssh/authorized_keys
sudo -u ${USER_NAME} chown -R ${USER_NAME} /home/${USER_NAME}
sudo -u ${USER_NAME} chgrp -R ${USER_NAME} /home/${USER_NAME}/.ssh/
# --------------------------------------------------------------------------------
# Changing SSHd default port
# --------------------------------------------------------------------------------
# sshd_config troubleshoot guide: https://stackoverflow.com/a/24724558
sed -i "/Port\s*22/d" /etc/ssh/sshd_config
sed -i "/PasswordAuthentication\s*yes/d" /etc/ssh/sshd_config
sed -i "/PermitRootLogin\s*yes/d" /etc/ssh/sshd_config
echo "Port "${SSHD_PORT} >> /etc/ssh/sshd_config
echo "PasswordAuthentication no" >> /etc/ssh/sshd_config
echo "PermitRootLogin no" >> /etc/ssh/sshd_config
semanage port -a -t ssh_port_t -p tcp ${SSHD_PORT}
firewall-cmd --permanent --zone=public --add-port=${SSHD_PORT}/tcp
firewall-cmd --permanent --zone=public --remove-service=ssh
firewall-cmd --reload
#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment