Script for 100% auto install on Debian 9 w/ Apache and PostgreSQL

I have been looking for a Debian based NC install script for a while that uses PostgreSQL instead of MySQL/MariaDB and have had no luck. I saw Onryo’s install script and really appreciated how well his script works. This gave me the idea to try and modify his script to work with PostgreSQL. I am not trying to take credit for Onryo’s work, I am just trying to make PostgreSQL work with his configuration.

Changes I made: updated OpenSSL to 1.1.0h and added DDNS client inadyn; swapped out LetsEncrypt with acme.sh; and included UFW firewall due to my needs. I attempted to update the script to include the necessary modifications for these new items.

I would love feed back on how I can improve the PostgreSQL portion of this script as I am a novice when it comes to scripting and PostgreSQL with NC.

#!/bin/sh


###############################################################################
## chmod +x nextcloud.sh && ./nextcloud.sh				     ##
## This script will install NextCloud on Debian 9 as follows:                ##
## php-fpm using unixsocket and own fpm pool for isolation                   ##
## Apache2 using MPM Event (should be a least as fast as nginx)              ##
## APCu for memory local cache                                               ##
## Redis on unixsocket for memory locking cache                              ##
## SSL using Lets Encrypt with secure TLS defaluts. A+ Rating                ##
## ModSecurity for real-time monitoring, logging, and access control         ##
##                                                                           ##
## By Erik Adler aka onryo erik.adler@mensa.se                               ##
## gpg --keyserver pgp.mit.edu --recv-keys 0x2B4B58FE                        ##
###############################################################################




# login user name. Change this!
nc_user='user'

# login user password. Change this!
nc_pw='password'

# local static ip. Change this!
staticip='ip'

# Enter your DuckDNS domain name
domainname='domian'

# Enter your DuckDNS token
duckDNStoken='token'

# email for vhost and cert.
email='webmaster@localhost'

# Change to version of NextCloud to download if not latest.
# latest.tar.bz2 is default
nextcloudVersion='latest.tar.bz2'

# Public gpg key used to verify NextCloud
# The key can be found at https://nextcloud.com/nextcloud.asc
# D75899B9A724937A is default
gpgKey='D75899B9A724937A'

# Path to NextCloud. Feel free to change this.
nc_home='/var/www/vhosts'

# Defaut is a random 32 char pw for NextCloud db admin user.
# A backup can be found under /root/admin_pw_backup.txt if needed.
db_admin_pw="$(tr -cd '[:alnum:]' < /dev/urandom | fold -w32 | head -n1)"

###############################################################################


[ "$(id -u)" = 0 ] || { printf 'Must be root to run script\n'; exit 1; }

hostName="$(hostname)"

## Add PostgreSQL Respository
sudo add-apt-repository "deb http://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main"
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

## Update to openssl 1.1.0h
yes | apt purge openssl && cd /usr/local/src/
wget http://ftp.nl.debian.org/debian/pool/main/o/openssl/libssl1.1_1.1.0h-4_armhf.deb
dpkg -i ./libssl1.1_1.1.0h-4_armhf.deb
wget http://ftp.nl.debian.org/debian/pool/main/o/openssl/openssl_1.1.0h-4_armhf.deb
dpkg -i openssl_1.1.0h-4_armhf.deb


apt update && apt upgrade -y 
apt install apt-transport-https lsb-release ca-certificates software-properties-common zip unzip screen curl socat ffmpeg libfile-fcntllock-perl -y


## Install inadyn
apt-get install inadyn
mv /etc/inadyn.conf /etc/inadyn.conf.bk

# Edit inadyn config file
cat >/etc/inadyn.conf<<EOF
--dyndns_server_name www.duckdns.org
--username nouser
--password $duckDNStoken
--update_period 60000
--forced_update_period 320000
--alias $domainname
--verbose 0
--dyndns_server_url /nic/?
--syslog
--background
EOF

# Add Inadyn Crontab
##insert sudo infront of the word "crontab" to insert into sudo crontab#
(crontab -l 2>/dev/null; echo "@reboot /usr/sbin/inadyn") | sort - | uniq - | crontab -

# Apache2 and PHP 7.0
apt-get install apache2 -y
apt-get install php7.0-fpm php7.0-gd php7.0-json php7.0-pgsql php7.0-curl -y
apt-get install php7.0-intl php7.0-mcrypt php7.0-imagick php7.0-xml -y
apt-get install php7.0-gmp php7.0-smbclient php7.0-ldap php7.0-imap -y
apt-get install php7.0-mbstring php7.0-bz2 php7.0-zip  -y

a2enmod proxy_fcgi rewrite headers env dir mime setenvif ssl
a2enconf php7.0-fpm
systemctl reload apache2

# Media functions and preview.
apt-get install ffmpeg libreoffice -y

# Setup database
apt install postgresql-10 -y

sudo -u postgres psql <<END
CREATE USER nextcloud WITH PASSWORD '$db_admin_pw';
CREATE DATABASE nextclouddb TEMPLATE template0 ENCODING 'UNICODE';
ALTER DATABASE nextclouddb OWNER TO nextcloud;
GRANT ALL PRIVILEGES ON DATABASE nextclouddb TO nextcloud;
END
service postgresql restart

# If for some reason you feel you need a NC pw backup. Only system root can read this.
echo "$db_admin_pw" > /root/admin_pw_backup.txt
chmod 400 /root/admin_pw_backup.txt

# Set up a php-fpm pool with a unixsocket
cat >/etc/php/7.0/fpm/pool.d/nextcloud.conf<<EOF
[Next Cloud]
user = www-data
group = www-data
listen = /run/php/php7.0-fpm.nextcloud.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 200
env[HOSTNAME] = $hostName
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
security.limit_extensions = .php
php_admin_value [cgi.fix_pathinfo] = 1
EOF

# Disable the idling example pool.
mv /etc/php/7.0/fpm/pool.d/www.conf /etc/php/7.0/fpm/pool.d/www.conf.backup

# Get NextCloud and verify the gpg signature. Change to the exact nc version
cd /tmp || { printf 'There is no /tmp dir\n'; exit 1; }
apt-get install dirmngr sudo -y
gpg --recv-keys "$gpgKey" || gpg --keyserver pgp.mit.edu "$gpgKey"
wget "https://download.nextcloud.com/server/releases/$nextcloudVersion"
wget "https://download.nextcloud.com/server/releases/$nextcloudVersion.asc"

gpg --verify "$nextcloudVersion.asc" "$nextcloudVersion" 2>&1 | grep  \
    'Good signature' || { printf 'BAD GPG SIGNATURE\n'; exit 1; }

tar xjfv "$nextcloudVersion"
mkdir -p $nc_home
mv nextcloud "$nc_home/"
chown -R www-data:www-data $nc_home/nextcloud

# Make SSL Directory
mkdir -p /etc/apache2/2.2/ssl

# Sets up the vhost
cat >/etc/apache2/sites-available/nextcloud.conf<<EOF
<VirtualHost *:80>
    ServerAdmin $email
    DocumentRoot $nc_home/nextcloud
    ServerName $domainname
    <Directory $nc_home/nextcloud/>
        AllowOverride All
        Options -Indexes +FollowSymlinks
        <IfModule mod_dav.c>
            Dav off
        </IfModule>
        SetEnv HOME $nc_home/nextcloud
        SetEnv HTTP_HOME $nc_home/nextcloud
    </Directory>
    <Directory $nc_home/nextcloud/data/>
        Require all denied
    </Directory>
    <FilesMatch \\.php$>
        SetHandler "proxy:unix:/run/php/php7.0-fpm.nextcloud.sock|fcgi://localhost"
    </FilesMatch>
    <IfModule mod_headers.c>
    	Header always add Strict-Transport-Security "max-age=15768000; includeSubDomains; preload"
    </IfModule>
</virtualhost>

<VirtualHost *:443>
    ServerAdmin $email
    DocumentRoot $nc_home/nextcloud
    ServerName $domainname
    <Directory $nc_home/nextcloud/>
        AllowOverride All
        Options -Indexes +FollowSymlinks
        <IfModule mod_dav.c>
            Dav off
        </IfModule>
        SetEnv HOME $nc_home/nextcloud
        SetEnv HTTP_HOME $nc_home/nextcloud
    </Directory>
    <Directory $nc_home/nextcloud/data/>
        Require all denied
    </Directory>
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php/php7.0-fpm.nextcloud.sock|fcgi://localhost"
    </FilesMatch>

        SSLEngine On
        SSLCertificateFile /etc/apache2/2.2/ssl/$domainname-cert.pem
        SSLCertificateKeyFile /etc/apache2/2.2/ssl/$domainname-key.pem
        SSLCertificateChainFile "/etc/apache2/2.2/ssl/letsencrypt.pem"

        SSLCACertificatePath "/etc/apache2/2.2/ssl/"
        SSLCACertificateFile "/etc/apache2/2.2/ssl/letsencrypt.pem"

	<IfModule mod_headers.c>
    		Header always add Strict-Transport-Security "max-age=15768000; includeSubDomains; preload"
    	</IfModule>

        ErrorLog /error.log
        #CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

EOF

a2dissite 000-default
a2ensite nextcloud

systemctl reload apache2
systemctl reload php7.0-fpm.service

# Install NextCloud
cd "$nc_home/nextcloud/" || { printf 'No nextcloud dir\n'; exit 1; }

# root uses sudo -u to allow very arcain password strings.
sudo -u www-data php "$nc_home/nextcloud/occ"  maintenance:install \
    --database 'pgsql' --database-name 'nextclouddb' --database-user 'nextcloud' \
    --database-pass "$db_admin_pw" --admin-user "$nc_user" --admin-pass "$nc_pw"

su -m www-data php -c "php $nc_home/nextcloud/occ config:system:set \
    trusted_domains 0 --value=$domainname"

su -m www-data php -c "php $nc_home/nextcloud/occ config:system:set \
    trusted_domains 1 --value=$staticip"

# Enable all previews
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enable_previews --value=true --type=boolean"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 0 --value='OC\\Preview\\PNG'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 1 --value='OC\\Preview\\JPEG'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 2 --value='OC\\Preview\\GIF'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 3 --value='OC\\Preview\\BMP'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 4 --value='OC\\Preview\\XBitmap'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 5 --value='OC\\Preview\\MarkDown'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 6 --value='OC\\Preview\\MP3'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 7 --value='OC\\Preview\\TXT'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 8 --value='OC\\Preview\\Illustrator'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 9 --value='OC\\Preview\\Movie'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 10 --value='OC\\Preview\\MSOffice2003'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 11 --value='OC\\Preview\\MSOffice2007'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 12 --value='OC\\Preview\\MSOfficeDoc'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 13 --value='OC\\Preview\\OpenDocument'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 14 --value='OC\\Preview\\PDF'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 15 --value='OC\\Preview\\Photoshop'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 16 --value='OC\\Preview\\Postscript'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 17 --value='OC\\Preview\\StarOffice'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 18 --value='OC\\Preview\\SVG'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 19 --value='OC\\Preview\\TIFF'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
  enabledPreviewProviders 20 --value='OC\\Preview\\Font'"

## APCu for local  memory cache
apt-get install php7.0-apcu -y
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
    memcache.local --value='\\OC\\Memcache\\APCu'"

##  Redis for distributed caching on unixsocket
apt-get install php7.0-redis redis-server -y

## Generate pw for redis connection
redis_pw="$(tr -cd '[:alnum:]' < /dev/urandom | fold -w32 | head -n1)"

sed -i "s/# requirepass foobared/requirepass ${redis_pw}/g" /etc/redis/redis.conf
sed -i 's/port 6379/port 0/g' /etc/redis/redis.conf
sed -i 's/# unixsocket/unixsocket/g' /etc/redis/redis.conf
sed -i 's/unixsocketperm 700/unixsocketperm 770/g' /etc/redis/redis.conf

usermod -a -G redis www-data
chown -R redis:www-data /var/run/redis

systemctl reload apache2
systemctl reload php7.0-fpm.service
systemctl enable redis-server
systemctl start redis-server

su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
    memcache.locking --value='\\OC\\Memcache\\Redis'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
    filelocking.enabled --value='true' --type=boolean"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
    redis host --value='/var/run/redis/redis.sock'"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
    redis port --value='0' --type=integer"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
    redis timeout --value='0' --type=integer"
su -m www-data -c "php $nc_home/nextcloud/occ config:system:set \
    redis password --value=$redis_pw"

systemctl restart redis-server.service

# Secure with https://www.modsecurity.org/about.html
# ModSecurity is a toolkit for real-time web application monitoring, logging, and access control.
# Default is to detect only but you can enable security to be active.

apt-get install libapache2-mod-security2  modsecurity-crs -y
mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
# whitelist to get started https://paste.debian.net/989100/
cd /etc/modsecurity || { printf 'No modsecurity dir\n'; exit 1; }
wget https://paste.debian.net/plain/989100
mv 989100 whitelist.conf
# Do not enable the next line unless you know what you are doing. This will enable active defence.
# sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine on/g' /etc/modsecurity/modsecurity.conf
# You can monitor tail -f /var/log/apache2/modsec_audit.log
systemctl reload apache2

## Back-Up opcache.ini

mv /etc/php/7.0/mods-available/opcache.ini /etc/php/7.0/mods-available/opcache.ini.bk

## Modify PHP opcache.ini
cat >/etc/php/7.0/mods-available/opcache.ini<<EOF
; configuration for php opcache module
; priority=10
zend_extension=opcache.so
opcache.enable=1
opcache.enable_cli=1
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.memory_consumption=256
opcache.save_comments=1
opcache.revalidate_freq=1
EOF

## Install and configure UFW
yes | apt install ufw
ufw allow 80/tcp && ufw allow 443/tcp && ufw allow 22/tcp && ufw logging medium
yes | ufw default deny incoming && yes | ufw enable && service ufw restart

##Clean-up packages not needed
sudo apt autoremove -y

## Install acme.sh
wget -O -  https://get.acme.sh | sh
export DuckDNS_Token="$duckDNStoken"

the devel branch has postgresql. :wink:
well. apache i have to add. someday. somehow.

This is why I love open source. I wrote this script thinking that just maybe somebody might want to use it. When Debian 10 comes out Ill probably write a new script. One that asks if PostgreSQL or Mariadb should be used. Same goes for Apache and Nginx.

All the best
Erik Adler aka Onryo