Skip to content

Instantly share code, notes, and snippets.

@SirNeural
Last active July 24, 2017 20:57
Show Gist options
  • Select an option

  • Save SirNeural/d8b5372a08c24f9fbfa1d77fefdfecc2 to your computer and use it in GitHub Desktop.

Select an option

Save SirNeural/d8b5372a08c24f9fbfa1d77fefdfecc2 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Check if using bash
if [ ! "$BASH_VERSION" ] ; then
echo "Please do not use sh to run this script ($0), just execute it directly with bash" 1>&2
exit 1
fi
# Set variables
read -p "Username: " USERNAME
read -s -p "Primary Password: " PASSWORD
echo
read -s -p "Repeat Primary Password: " PASSWORD
echo
read -s -p "Htpasswd Password: " HTPASSWORD
echo
read -s -p "Repeat Htpasswd Password: " HTPASSWORD
echo
read -p "Project Name: " PROJECT
read -p "URL: (example.com) " URL
SYNCPORT='9024'
# Add the syncthing release PGP keys:
curl -s https://syncthing.net/release-key.txt | apt-key add -
# Add the "release" channel to your APT sources:
echo "deb http://apt.syncthing.net/ syncthing release" | tee /etc/apt/sources.list.d/syncthing.list
# Find IP Address
IP=""
if [ -f /usr/bin/ec2metadata ]
then
IP=`timeout 1 ec2metadata --public-hostname`
fi
if [ "$IP" = "unavailable" ]
then
IP=`curl http://ipinfo.io/ip 2>/dev/null | egrep -o "[0-9\.]*"`
fi
if [ "$IP" = "" ]
then
IP=`ifconfig | perl -ple 'print $_ if /inet addr/ and $_ =~ s/.*inet addr:((?:\d+\.){3}\d+).*/$1/g ;$_=""' | grep -v ^\s*$ | grep -v 127.0.0.1 | head -n 1`
fi
if [ "$IP" = "" ]
then
IP=`cat /etc/hostname | head -n 1`
fi
# Create project folder, written in 4 single mkdir-statements to make sure this runs everywhere without problems
mkdir "/var/www"
mkdir "/var/www/html"
# Update repositories
apt update
apt -y upgrade
# Add repositories
apt -y install python-software-properties
add-apt-repository -y ppa:rwky/redis
apt update
# Set firewall options
ufw allow ssh
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 587/tcp
ufw allow 1723/tcp
ufw allow $SYNCPORT/tcp
ufw allow 22000/tcp
ufw allow 21027/udp
sed -ie 's/DEFAULT_FORWARD_POLICY="DROP"/DEFAULT_FORWARD_POLICY="ACCEPT"/' /etc/default/ufw
sed -i "1i# START OPENVPN RULES\n# NAT table rules\n*nat\n:POSTROUTING ACCEPT [0:0]\n# Allow traffic from OpenVPN client to eth0\n\n-A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE\nCOMMIT\n# END OPENVPN RULES\n" /etc/ufw/before.rules
sed -i "29i# allow GRE protocol for VPN\n-A ufw-before-input -p 47 -j ACCEPT\n" /etc/ufw/before.rules
echo "y" | ufw enable
# Set configuration options
debconf-set-selections <<< "mysql-server mysql-server/root_password password $PASSWORD"
debconf-set-selections <<< "mysql-server mysql-server/root_password_again password $PASSWORD"
apt install -y nginx mysql-server php-fpm php-mysql php-mbstring php-gettext php-mcrypt php-curl php-cli php-zip redis-server php-redis php-libsodium
# Change PHP-FPM settings
sed -i '/cgi.fix_pathinfo=1/c cgi.fix_pathinfo=0' /etc/php/7.0/fpm/php.ini
sed -i '/max_execution_time = 30/c max_execution_time = 300' /etc/php/7.0/fpm/php.ini
sed -i '/upload_max_filesize = 2M/c upload_max_filesize = 8M' /etc/php/7.0/fpm/php.ini
sed -i '/listen = 127.0.0.1:9000/c listen = /var/run/php/php7.0-fpm.sock' /etc/php/7.0/fpm/pool.d/www.conf
# Create database
echo "CREATE DATABASE ${PROJECT,,}" | mysql -uroot -p$PASSWORD
# Enable PHP7 Mods
phpenmod mcrypt
# Install PHPMyAdmin
debconf-set-selections <<< "phpmyadmin phpmyadmin/dbconfig-install boolean true"
debconf-set-selections <<< "phpmyadmin phpmyadmin/app-password-confirm password $PASSWORD"
debconf-set-selections <<< "phpmyadmin phpmyadmin/mysql/admin-pass password $PASSWORD"
debconf-set-selections <<< "phpmyadmin phpmyadmin/mysql/app-pass password $PASSWORD"
debconf-set-selections <<< "phpmyadmin phpmyadmin/reconfigure-webserver multiselect none"
apt -y install phpmyadmin
# Install miscellaneous packages
apt -y install openssl git curl zip screen syncthing apache2-utils
# Install Composer
curl -s https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
# Install Laravel
composer global require "laravel/installer"
PATH=~/.composer/vendor/bin:$PATH
# Setup a new project
cd /var/www/html
laravel new ${PROJECT,,}
chown -R www-data ${PROJECT,,}/storage
chown -R www-data ${PROJECT,,}/bootstrap/cache
chmod -R 755 ${PROJECT,,}/storage
chmod -R 755 ${PROJECT,,}/bootstrap/cache
# Install Project Dependencies
cd ${PROJECT,,}
composer require "laravelcollective/html" \
"laravel/tinker" \
"spatie/laravel-backup" \
"tymon/jwt-auth" \
"half2me/curlx" \
"guzzlehttp/guzzle" \
"anhskohbo/no-captcha" \
"pragmarx/google2fa" \
"bacon/bacon-qr-code":"~1.0" \
"snowfire/beautymail" \
"cmgmyr/messenger" \
"olssonm/l5-zxcvbn" \
"torann/geoip" \
"gloudemans/shoppingcart"
# Register service provider and add alias
sed -i "s/'name' => 'Laravel',/'name' => '${PROJECT}',/g" /var/www/html/${PROJECT,,}/config/app.php
sed -i "s/'timezone' => 'UTC',/'timezone' => 'America\\/Phoenix',/g" /var/www/html/${PROJECT,,}/config/app.php
sed -i "/Illuminate\\\Auth\\\AuthServiceProvider::class,/a \\\tLaravel\\\Tinker\\\TinkerServiceProvider::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/Illuminate\\\Auth\\\AuthServiceProvider::class,/a \\\tTymon\\\JWTAuth\\\Providers\\\JWTAuthServiceProvider::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/Illuminate\\\Auth\\\AuthServiceProvider::class,/a \\\tCollective\\\Html\\\HtmlServiceProvider::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/Illuminate\\\Auth\\\AuthServiceProvider::class,/a \\\tSpatie\\\Backup\\\BackupServiceProvider::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/Illuminate\\\Auth\\\AuthServiceProvider::class,/a \\\tOlssonm\\\Zxcvbn\\\ZxcvbnServiceProvider::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/Illuminate\\\Auth\\\AuthServiceProvider::class,/a \\\tCmgmyr\\\Messenger\\\MessengerServiceProvider::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/Illuminate\\\Auth\\\AuthServiceProvider::class,/a \\\tAnhskohbo\\\NoCaptcha\\\NoCaptchaServiceProvider::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/Illuminate\\\Auth\\\AuthServiceProvider::class,/a \\\tSnowfire\\\Beautymail\\\BeautymailServiceProvider::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/Illuminate\\\Auth\\\AuthServiceProvider::class,/a \\\tPragmaRX\\\Google2FA\\\Vendor\\\Laravel\\\ServiceProvider::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/Illuminate\\\Auth\\\AuthServiceProvider::class,/a \\\tTorann\\\GeoIP\\\GeoIPServiceProvider::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/Illuminate\\\Auth\\\AuthServiceProvider::class,/a \\\tGloudemans\\\Shoppingcart\\\ShoppingcartServiceProvider::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/'App' => Illuminate\\\Support\\\Facades\\\App::class,/a \\\t'Html' => Collective\\\Html\\\HtmlFacade::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/'App' => Illuminate\\\Support\\\Facades\\\App::class,/a \\\t'Zxcvbn' => Olssonm\\\Zxcvbn\\\Facades\\\Zxcvbn::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/'App' => Illuminate\\\Support\\\Facades\\\App::class,/a \\\t'JWTAuth' => Tymon\\\JWTAuth\\\Facades\\\JWTAuth::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/'App' => Illuminate\\\Support\\\Facades\\\App::class,/a \\\t'JWTFactory' => Tymon\\\JWTAuth\\\Facades\\\JWTFactory::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/'App' => Illuminate\\\Support\\\Facades\\\App::class,/a \\\t'Google2FA' => PragmaRX\\\Google2FA\\\Vendor\\\Laravel\\\Facade::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/'App' => Illuminate\\\Support\\\Facades\\\App::class,/a \\\t'Messenger' => Cmgmyr\\\Messenger\\\MessengerServiceProvider::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/'App' => Illuminate\\\Support\\\Facades\\\App::class,/a \\\t'NoCaptcha' => Anhskohbo\\\NoCaptcha\\\Facades\\\NoCaptcha::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/'App' => Illuminate\\\Support\\\Facades\\\App::class,/a \\\t'BeautyMail' => Snowfire\\\Beautymail\\\BeautymailServiceProvider::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/'App' => Illuminate\\\Support\\\Facades\\\App::class,/a \\\t'GeoIP' => Torann\\\GeoIP\\\Facades\\\GeoIP::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "/'App' => Illuminate\\\Support\\\Facades\\\App::class,/a \\\t'Cart' => Gloudemans\\\Shoppingcart\\\Facades\\\Cart::class," /var/www/html/${PROJECT,,}/config/app.php
sed -i "s/'name' => 'Example',/'name' => env('APP_NAME', 'admin@${URL}'),/g" /var/www/html/${PROJECT,,}/config/mail.php
sed -i "s/'address' => 'hello@example.com',/'address' => env('APP_EMAIL', '${PROJECT}'),/g" /var/www/html/${PROJECT,,}/config/mail.php
# Publish config file
php artisan vendor:publish --provider="Spatie\Backup\BackupServiceProvider"
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"
php artisan vendor:publish --provider="Snowfire\Beautymail\BeautymailServiceProvider"
php artisan vendor:publish --provider="Cmgmyr\Messenger\MessengerServiceProvider"
php artisan vendor:publish --provider="Torann\GeoIP\GeoIPServiceProvider" --tag=config
php artisan jwt:generate
php artisan geoip:update
# Run setup for syncthing
syncthing -generate="/root/.config/syncthing"
# Replace default configuration
sed -e "s/<gui enabled=\"true\" tls=\"false\">/<gui enabled=\"true\" tls=\"true\">/g" /root/.config/syncthing/config.xml > /root/.config/syncthing/config.xml.tmp && mv /root/.config/syncthing/config.xml.tmp /root/.config/syncthing/config.xml
sed -e "s/<address>127.0.0.1:8384<\/address>/<address>0.0.0.0:$SYNCPORT<\/address>/g" /root/.config/syncthing/config.xml > /root/.config/syncthing/config.xml.tmp && mv /root/.config/syncthing/config.xml.tmp /root/.config/syncthing/config.xml
# Set a symbolic link to connect phpmyadmin and root web directory
ln -s /usr/share/phpmyadmin /var/www/html/${PROJECT,,}/public
# Set Password
VHOST=$(cat <<EOF
AuthType Basic
AuthName "Restricted Files"
AuthUserFile /etc/phpmyadmin/.htpasswd
Require valid-user
EOF
)
echo "$VHOST" > /usr/share/phpmyadmin/.htaccess
htpasswd -c -b -B -C 14 /etc/phpmyadmin/.htpasswd $USERNAME $HTPASSWORD
# Setup ssl certificates
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/ssl.key -out /etc/ssl/ssl.crt -subj "/C=US/CN=www.$URL/emailAddress=admin@$URL"
# Replace default configuration
VHOST=$(cat <<EOF
server {
listen 80;
server_name $IP;
return 301 https://$URL;
}
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
listen 443 ssl;
listen [::]:443 ssl ipv6only=on;
root /var/www/html/${PROJECT,,}/public;
index index.php index.html index.htm;
server_name $URL www.$URL;
ssl_certificate /etc/ssl/ssl.crt;
ssl_certificate_key /etc/ssl/ssl.key;
sendfile on;
error_page 404 /index.php;
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
location /phpmyadmin {
auth_basic "Restricted Files";
auth_basic_user_file /etc/phpmyadmin/.htpasswd;
}
location / {
try_files \$uri \$uri/ /index.php\$is_args\$args;
}
if (!-d \$request_filename) {
rewrite ^/(.+)/\$ /\$1 permanent;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)\$;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
fastcgi_intercept_errors off;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
}
location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
}
location ~* .*/\..* {
deny all;
}
location ~* /(\.|wp-config.php|readme.html|license.txt|schema.txt|password.txt|passwords.txt) {
deny all;
}
location ~* \.(engine|inc\.php|class\.php|phps|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$|^(\..*|Entries.*|Repository|Root|Tag|Template)$|\.php_ {
deny all;
}
location ~ ~\$ {
access_log off;
log_not_found off;
deny all;
}
}
EOF
)
echo "$VHOST" > /etc/nginx/sites-available/default
# Optimize Nginx
WORKER_CONNECTIONS=`ulimit -n`
VHOST=$(cat <<EOF
user www-data;
worker_processes auto;
pid /run/nginx.pid;
worker_rlimit_nofile 100000;
events {
use epoll;
worker_connections ${WORKER_CONNECTIONS};
multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_requests 100000;
keepalive_timeout 45;
reset_timedout_connection on;
client_body_timeout 10;
send_timeout 2;
types_hash_max_size 2048;
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 5;
open_file_cache_errors off;
server_tokens off;
client_body_buffer_size 16k;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 2 4k;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
gzip_min_length 1024;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "MSIE [1-6]\.";
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_vary on;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
EOF
)
echo "$VHOST" > /etc/nginx/nginx.conf
# Restart web services
service php7.0-fpm restart
service nginx restart
# Secure mysql installation (mysql_secure_installation)
echo "DELETE FROM mysql.user WHERE User='';" | mysql -uroot -p$PASSWORD
echo "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');" | mysql -uroot -p$PASSWORD
echo "DROP DATABASE IF EXISTS test;" | mysql -uroot -p$PASSWORD
echo "DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';" | mysql -uroot -p$PASSWORD
echo "FLUSH PRIVILEGES;" | mysql -uroot -p$PASSWORD
# final feedback
echo "Voila!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment