Bash Install script for my servers

I’m attempting to write an service install and configuration script for my servers. This is the script in it’s nearly finished state. I’m currently ironing out my confusion regarding apache configs and WSGI services through apache (thread expected to arrive in a few days unless I solve it before then).

I hope to receive some criticism on it and I also hope for it to be of use for somebody else wishing to run similar setups.

#! /bin/bash

#Give instructions
echo "This script needs you to have port forwarding and DNS set up correctly for the ssl generation to function.

If this isn't done press ctrl+c to cancel execution
"
sleep 2

# todo: 
#		Setup ssl for nextcloud
#		Generate directory system explanation in file /srv/help (I keep forgetting!)
#		Check that mysql uses socket
#		Correct permissions for /srv/onion1 so tor starts
#		Add passwords to deluge correctly

echo "Installing relevant software"

echo "
deb http://ftp.debian.org/debian jessie-backports main
" >> /etc/apt/sources.list

read -s -p "Enter mysql root password and make note of it securely
(it won't be visible as you write)
" DBPASSWD

read -s -p "Enter nextcloud admin password and make note of it securely
(it won't be visible as you write)
" NEXTCLOUD_PASSWD

read -s -p "Enter deluge login password and make note of it securely
(it won't be visible as you write)
" DELUGE_PASSWORD

apt-get -q update

echo "mysql-server mysql-server/root_password select $DBPASSWD" | debconf-set-selections
echo "mysql-server mysql-server/root_password_again select $DBPASSWD" | debconf-set-selections
apt-get -y -q install tor sudo openssh-server samba deluged deluge-web apache2-utils apache2 php php-mysql php-gd php-curl php-zip php-dom php-xml php-mbstring mysql-server
#apt-get -y -q install python-certbot-apache -t jessie-backports


echo "Adding users and groups"
echo "Set password and other information for local user sid"
adduser sid
addgroup torrent
adduser sid torrent
adduser debian-deluged torrent
addgroup onion
adduser sid onion
addgroup stor
adduser sid stor

echo "Configuring directories and permissions"

#Making directories
mkdir /srv/onion1
mkdir /srv/onion2
mkdir /srv/stor
mkdir /srv/old
mkdir /srv/torrent
mkdir /srv/torrent/torrent-files
mkdir /srv/torrent/downloads
mkdir /srv/public
mkdir /srv/www
mkdir /srv/db
#Linking /home in case of storing home on hdd
ln -s /home /srv/home

#Setting permissions
chmod -R 0750 /srv
chmod 0775 /srv
chmod -R 0775 /srv/stor
chmod -R 0755 /srv/old
chmod -R 0775 /srv/public
chmod 0775 /srv/www
chmod 0640 /srv/onion1
chmod 0640 /srv/onion2

chown -R sid:sid /srv
chown -R sid:torrent /srv/torrent
chown -R sid:stor /srv/stor
chown -R debian-tor:onion /srv/onion1
chown -R debian-tor:onion /srv/onion2
chown -R www-data:www-data /srv/public
chown -R www-data:www-data /srv/www

#add user sid to samba
echo "set password for samba user sid"
smbpasswd -a sid

echo "Configuring ssh and sftp for connection over tor, web and LAN"
echo "
#Allow connections to these adresses
Host *.onion *sidju* 10.* 192.168.* localhost 127.0.0.1

#Global settings 
Match originalhost *
#compress data to minimize bandwidth use
Compression yes
#Limit password retries
NumberOfPasswordPrompts 2
#Passwords are allowed. Use identity keys only for improved security
PasswordAuthentication yes
#root login is disabled by default

" > /etc/ssh/ssh_config

invoke-rc.d sshd restart

echo "Configuring hidden service hosting in /srv/onion1"

cp /etc/tor/torrc /etc/tor/torrc.old

echo "
User debian-tor
#Configure hidden services
HiddenServiceDir /srv/onion1

HiddenServicePort 80 127.0.0.1:80
HiddenServicePort 83 127.0.0.1:83
HiddenServicePort 8112 127.0.0.1:8112
HiddenServicePort 22 127.0.0.1:22

#Require password to connect to service
HiddenServiceAuthorizeClient stealth sid,sidserv,other
" > /etc/tor/torrc

#Restart tor when directory permissions are correct for the configuration to work
invoke-rc.d tor restart

echo "Configuring samba sharing of /srv/stor, /srv + / (for administration) and home directories"

#set error file when smb crasches
echo "#! /bin/bash
touch /home/sid/SambaHasCrasched!!!!" > /etc/samba_crasch_action.sh

echo "[global]
workgroup = SIDNET
security = user
map to guest = bad user
guest account = nobody
#Store passwords encrypted
encrypt passwords = yes
server role = standalone server
#setup logging
log file = /var/log/samba/log.%m
max log size = 100
syslog = 0
#set crash warning in visible location
panic action = /etc/samba_crash_action.sh
#Setup user backend
passdb backend = tdbsam
#Set root permissions for root (uneccesary?)
admin users = root
#Disable irrelevant accounts
invalid users = daemon bin sys sync games man lp mail news uucp proxy www-data backup list irc gnats systemd-timesync systemd-network systemd-resolve systemd-bus-proxy Debian-exim messagebus statd debian-deluged sshd debian-tor
#Limit connections
deadtime = 60
max connections = 20
#Share the connected user's home directory
[homes]
read only = no
browseable = no
create mask = 0700
directory mask = 0700
follow symlinks = no
invalid users = nobody

#share /srv/stor for general access
[stor]
path = /srv/stor
read only = yes
create mask = 0755
directory mask = 0755
guest ok = yes
follow symlinks = no

#share /srv for administration
[srv]
path = /srv
read only = no
valid users = root sid
follow symlinks = no
administrative share = yes

#share / for administration
[root]
path = /
read only = no
valid users = root
follow symlinks = yes
administrative share = yes

" > /etc/samba/smb.conf

invoke-rc.d smbd restart
invoke-rc.d nmbd restart

echo "Configuring deluge"

mkdir /var/log/deluge
rmdir /var/log/deluged
chown -R debian-deluged /var/lib/deluged
chown -R debian-deluged /var/log/deluge

#Autostart daemon
echo "[Unit]
Description=Deluge Bittorrent Client Daemon
After=network-online.target

[Service]
Type=simple
User=debian-deluged
Group=torrent
UMask=007

ExecStart=/usr/bin/deluged -d -l /var/log/deluge/daemon.log -L info

Restart=on-failure

# Configures the time to wait before service is stopped forcefully.
TimeoutStopSec=300

[Install]
WantedBy=multi-user.target
" > /etc/systemd/system/deluged.service

systemctl enable /etc/systemd/system/deluged.service
systemctl start deluged

#Autostart web ui
echo "[Unit]
Description=Deluge Bittorrent Client Web Interface
After=network-online.target

[Service]
Type=simple

User=debian-deluged
Group=torrent
UMask=027

ExecStart=/usr/bin/deluge-web -l /var/log/deluge/web-ui.log -L info

Restart=on-failure

[Install]
WantedBy=multi-user.target
" > /etc/systemd/system/deluge-web.service

systemctl enable /etc/systemd/system/deluge-web.service
systemctl start deluge-web

echo "Waiting for deluge"
echo "4"
sleep 2
echo "3"
sleep 2
echo "2"
sleep 2
echo "1"
sleep 2
echo "0"

systemctl stop deluge-web
systemctl stop deluged

#Write config file for deluge
cp ./core.conf /var/lib/deluged/.config/deluge/core.conf

#Add authentications
echo "sid:$DELUGE_PASSWORD:10" >> /var/lib/deluged/.config/deluge/auth

#last permissions check
chown -R debian-deluged /var/lib/deluged
chown -R debian-deluged /var/log/deluge

systemctl start deluged
systemctl start deluge-web

#Setup apache2

#Automate cleaning of the shared dir (only symlinks allowed)
#todo: chron job for this (and backups)
echo "#! /bin/bash
find /srv/public -type f -delete"

#Backup default config file (useful information)
cp /etc/apache2/apache2.conf /etc/apache2/apache2.conf.old

#Write new config file
echo "ServerRoot \"/etc/apache2\"
Mutex file:\${APACHE_LOCK_DIR} default
PidFile \${APACHE_PID_FILE}

#Configure general behavior
Timeout 512
KeepAlive On
MaxKeepAliveRequests 32
KeepAliveTimeout 16

#Set process owner and rights
User \${APACHE_RUN_USER}
Group \${APACHE_RUN_GROUP}

#Configure logging
HostnameLookups Off
ErrorLog \${APACHE_LOG_DIR}/error.log
LogLevel warn
#Custom log formats (for use with CustomLog setting)
LogFormat \"%v:%p %h %l %u %t \\\"%r\\\" %>s %O \\\"%{Referer}i\\\" \\\"%{User-Agent}i\\\"\" vhost_combined
LogFormat \"%h %l %u %t \\\"%r\\\" %>s %O \\\"%{Referer}i\\\" \\\"%{User-Agent}i\\\"\" combined
LogFormat \"%h %l %u %t \\\"%r\\\" %>s %O\" common
LogFormat \"%{Referer}i -> %U\" referer
LogFormat \"%{User-agent}i\" agent 

#Configure automatic adding of settings from directories
IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf

#ports to listen on read from ports.conf file (unused)
#Include ports.conf

#Forbid web access to all directories by default
<Directory />
	AllowOverride None
	Require all denied
</Directory>

#read access controlling files and prevent 
#them from being viewed from the web
AccessFileName .htaccess
<FilesMatch \"^\.ht\">
		Require all denied
</FilesMatch>

#Read config from sites-enabled and conf-enabled

IncludeOptional sites-enabled/*.conf
IncludeOptional conf-enabled/*.conf

" > /etc/apache2/apache2.conf

#Configure sharing of the public directory

echo "#Set the directory to be shared behind port 83 (ascii "S")
Listen 83
<VirtualHost *:83>
	ServerName sidju.tech
	DocumentRoot /srv/public
</VirtualHost>

#Set correct sharing for directory
<Directory /srv/public>
	Options Indexes FollowSymLinks
	AllowOverride None
	Require all granted
</Directory>
" > /etc/apache2/sites-available/html_83.conf

touch /etc/apache2/mime.types

#Preparing nextcloud installation

echo "Downloading nextcloud installation files"
wget https://download.nextcloud.com/server/releases/nextcloud-12.0.0.tar.bz2 -P /srv/www/

echo "Extracting....."
tar -xjf /srv/www/nextcloud-*.tar.bz2 -C /srv/www/

rm -f /srv/www/nextcloud-*

chown -R www-data:www-data /srv/www/nextcloud/

cd /srv/www/nextcloud/

#Check function of this next part

#Setup mysql database and user for owncloud

systemctl stop mariadb

#Move mysql/mariadb directory
rsync -av /var/lib/mysql/ /srv/db/
rsync -av /var/lib/mysql/ /var/lib/mysql.old/

mount --bind /srv/db /var/lib/mysql

echo "/srv/db /var/lib/mysql none defaults,bind 0 0" >> /etc/fstab

echo "
#Secure server side config
[mysqld]
#The datadir is stored in /srv/www/db/
datadir=/srv/www/db
#Run through socket without networking
socket=/var/run/mysqld/mysqld.sock
skip-networking


[mysql]
socket=/var/run/mysqld/mysqld.sock
protocol=SOCKET

" > /etc/mysql/my.cnf

chmod 0600 /etc/mysql/my.cnf

#Configure php-mysql to connect to the right socket (no need?)


echo "reenabling mysqld with new config"
#Start mysqld again
systemctl enable mariadb
systemctl start mariadb

#Harden security
mysql --user=root --password=$DBPASSWD -e "DELETE FROM mysql.user WHERE User='';"
mysql --user=root --password=$DBPASSWD -e "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');"
mysql --user=root --password=$DBPASSWD -e "DROP DATABASE test;"
mysql --user=root --password=$DBPASSWD -e "DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';"

#Add database nextcloud and user nextcloud as admin of it 
# create random password
NEXTCLOUD_DB_PASSWD="$(openssl rand -base64 12)"

MAINDB="nextcloud"

mysql --user=root --password=$DBPASSWD -e "CREATE DATABASE ${MAINDB} /*\!40100 DEFAULT CHARACTER SET utf8 */;"
mysql --user=root --password=$DBPASSWD -e "CREATE USER ${MAINDB}@localhost IDENTIFIED BY '${NEXTCLOUD_DB_PASSWD}';"
mysql --user=root --password=$DBPASSWD -e "GRANT ALL PRIVILEGES ON ${MAINDB}.* TO '${MAINDB}'@'localhost';"
mysql --user=root --password=$DBPASSWD -e "FLUSH PRIVILEGES;"

echo $NEXTCLOUD_DB_PASSWD >> tmp_pass.txt
echo $NEXTCLOUD_PASSWD >> tmp_pass2.txt

#test occ command outside of script first
cd /srv/www/nextcloud
sudo -u www-data php occ maintenance:install --database "mysql" --database-name "nextcloud" --database-user "nextcloud" --database-pass "$(cat tmp_pass.txt)" --admin-user "sid" --admin-pass "$(cat tmp_pass2.txt)"
cd /mnt

#Set port 80 and 443 to owncloud

echo "#Share nextcloud behind port 80
Listen 80

<VirtualHost *:80>
        ServerName sidju.tech
        DocumentRoot /srv/www/nextcloud
</VirtualHost>

#Use alias if other service in web-root
Alias /nextcloud "/var/www/nextcloud/"

<Directory /srv/www>
  Options +FollowSymlinks
  AllowOverride All
  Require all granted

 <IfModule mod_dav.c>
  Dav off
 </IfModule>

 SetEnv HOME /srv/www/nextcloud
 SetEnv HTTP_HOME /srv/www/nextcloud

</Directory>" > /etc/apache2/sites-available/nextcloud_80.conf

echo "testing certbot to generate config for port 443"

#certbot --apache

echo "#Share nextcloud behind port 443
<IfModule mod_ssl.c>
        Listen 443
        <VirtualHost *:443>
                ServerAdmin [email protected]
                DocumentRoot /srv/www/nextcloud
                
                SSLEngine on
                SSLCertificateFile /srv/www/ssl/sidju.tech.pem
                SSLCertificateKeyFile /src/www/ssl/sidju.tech.key

" > /tmp/tmp.conf # /etc/apache2/sites-available/nextcloud_443.conf

#Configure what services are enabled
a2dissite 000-default.conf
a2ensite html_83.conf
a2ensite nextcloud_80.conf

#Enable some mods for nextcloud's sake
a2enmod rewrite
a2enmod headers
a2enmod env
a2enmod dir
a2enmod mime

systemctl enable apache2
systemctl stop apache2
systemctl start apache2

#Instruct the users

#Write help file to /srv/help.txt
echo "
Before nextcloud can be used you must run the configuration wizard available on port 80 of this server. 
In the top of the page you enter username and password for the admin user.

In the bottom enter database user \"root\" and the database password you chose before. Preferably you'll name the database nextcloud...

To access the different services users need to be members of the groups
onion (read .onion urls and passphrases in /srv/onion*),
torrent (rw permission in otherwise locked /srv/torrents) and 
stor (rw instead of ro in /srv/stor).
For samba access users also need to be added through \"smbpasswd -a [username]\"

This has been written to the file /srv/help.txt" > /srv/help.txt

#add space for readability
echo "


"

#Print help file on screen
cat /srv/help.txt

Ps. I’m aware that there is a password in this script. It is a placeholder which will be replaced with another password prompt later, when testing is done and the script finalized.

EDIT: Updated on april 6:th

EDIT 2: I have foregone this in favour of freenas. Latest version is here for whomever might wish to use it.

2 Likes

Just a nitpick, but your comment:

# All authenticated users may read any collection starting with "public.".

Will actually print out as:
# All authenticated users may read any collection starting with public..

Since its already inside double quotes. You can use single quotes or even heredoc instead.

2 Likes

Hey there

Thanks for sharing the script :).

I'm just curious, have you ever tried Ansible oder something similar? I never used it, but I'm thinking about using it for such tasks.. Let me know if you do.. :)

I haven't even read about it. Will do though! Nice tip!

Missed escaping those quotes. They were meant to be escaped and enter the file. I suppose that explains my problems with making the permissions work...........
Thanks a lot for helping me proofread!

You're welcome. I'm not sure if it covers your use case exactly, and it's hard to reason about as developer (I'm not a sysadmin..) :)

I have decided to forego radicale in favor of Nextcloud. Currently hoping for help on apache config in https://forum.level1techs.com/t/help-with-apache-config/113286

The escape character will fix it, right?

Different quote types usually work but sometimes it's necessary to have more then two.

After a longer break than intended I'm now back to working on it.
(code updated, all except ssl works and data storage location for mysql is due to be changed)

The remaining things needed for me to continue are port forwarding and DNS to be setup on my network. Might take a few weeks before next burst, but after that it ought to be done.

Criticism is welcomed as usual.

Escape characters are the way I've dealt with it in the apache.conf file. Works beautifully