Home install folder added, this needs more work before being tested

This commit is contained in:
Papa Dragon 2022-03-06 00:58:18 +01:00
parent 1c5b2b0602
commit 7d2f532108
5 changed files with 1303 additions and 0 deletions

143
.homeinstall/README.md Normal file
View file

@ -0,0 +1,143 @@
# How to use
## Disclaimers
- This script does work with Debian 11 only.
- This script has to be used on a fresh debian install only (it does not take account for a possibly already installed and configured webserver or sql implementation). You may use it to install several hub/instances on the same server, though.
## Preconditions
Hardware
+ Internet connection and router at home
+ Mini-pc connected to your router (a Raspberry 3 will do for very small Hubs)
+ USB drive for backups
Software
+ Fresh installation of Debian 11 (Bullseye)
+ Router with open ports 80 and 443 for your web server
You can of course run the script on a VPS or any distant server as long as the above sotfware requirements are satisfied.
## How to run the script
+ Register your own domain (for example at selfHOST) or a free subdomain (for example at freeDNS)
+ Log on to your fresh Debian
- apt-get install git
- mkdir -p /var/www
- cd /var/www
- git clone https://codeberg.org/streams/streams.git html (you can replace "html" with any name you like, which you'll have to do if you plan to have more than one hub/instance running on your server)
- cd html/.homeinstall
- cp server-config.txt.template server-config.txt
- nano server-config.txt
- Read the comments carefully
- Enter your values: db pass, domain, values for dyn DNS
- Prepare your external disk for backups
- ./server-setup.sh as root
- ... wait, wait, wait until the script is finished
+ Open your domain with a browser and step throught the initial configuration of your hub/instance.
## Optional - Set path to imagemagick
In Admin settings of your hub/server or via terminal
cd /var/www/html
util/config system.imagick_convert_path /usr/bin/convert
## Optional - Switch verification of email on/off
Do this just before you register the first user.
In Admin settings of your hub/instance or via terminal
cd /var/www/html
Check the current setting
util/config system verify_email
Switch the verification on/off (1/0)
util/config system verify_email 0
## What the script will do for you...
+ install everything required by your website, basically a web server (Apache or Nginx), PHP, a database (MySQL), certbot,...
+ create a database
+ run certbot to have everything for a secure connection (httpS)
+ create a script for daily maintenance
- backup to external disk (certificates, database, /var/www/)
- renew certfificate (letsencrypt)
- update of your hub/instance (git)
- update of Debian
- restart
+ create cron jobs for
- DynDNS (selfHOST.de or freedns.afraid.org) every 5 minutes
- Run.php for your hub/instance every 10 minutes
- daily maintenance script every day at 05:30
The script is known to work without adjustments with
+ Hardware
- Mini-PC with Debian 11 (bullseye), or
- Rapberry 3 with Raspbian, (previous version of the script, with Debian 10)
- Rapberry 4 with Raspbian, (previous version too, with Debian 10)
+ DynDNS
- selfHOST.de
- freedns.afraid.org
# Step-by-Step - some Details
## Preparations
## Configure your Router
Your webserver has to be visible in the internet.
Open the ports 80 and 443 on your router for your Debian. Make sure your web server is marked as "exposed host".
## Preparations Dynamic IP Address
Follow the instructions in .homeinstall/server-config.txt.
In short...
Your server must be reachable by a domain that you can type in your browser
cooldomain.org
You can use subdomains as well
my.cooldomain.org
There are two ways to get a domain...
### Method 1: Buy a Domain
...for example buy at selfHOST.de
The cost is 1,50 € per month (2019).
### Method 2: Register a free subdomain
...for example register at freedns.afraid.org
## Note on Rasperry
Previous versions of the script were tested with a Raspberry 3 and a Raspberry 4 both with Raspian, Debian 10.
It is recommended to run the Raspi without graphical frontend (X-Server). Use...
sudo raspi-config
to boot the Raspi to the client console.
DO NOT FORGET TO CHANGE THE DEFAULT PASSWORD FOR USER PI!
## Reminder for Different Web Wervers
For those of you who feel adventurous enough to use a different web server (i.e. Lighttpd...), don't forget that this script will install Apache or Nginx and that you can only have one web server listening to ports 80 & 443. Also, don't forget to tweak your daily shell script in /var/www/ accordingly.

View file

@ -0,0 +1,10 @@
location /adminer {
root /usr/share/adminer;
index index.php index.html index.htm;
location ~ ^/adminer/(.+\.php)$ {
try_files $uri $uri/ /index.php?$query_string;
fastcgi_pass unix:/var/run/php/php-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}

View file

@ -0,0 +1,146 @@
##
# Nginx block configuration template
# based on the example created by Olaf Conradi
#
# The files generated with this template will be added to
# /etc/nginx/sites-available & /etc/nginx/sites-enabled (symlink)
##
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
#
# http://wiki.nginx.org/Pitfalls
# http://wiki.nginx.org/QuickStart
# http://wiki.nginx.org/Configuration
##
##
# This configuration assumes
# You filled the zotserver-config.txt file
# Your domain/subdomain is functionnal
# You want all traffic to be https
# You have PHP FastCGI Process Manager (php-fpm) running on localhost
##
server {
listen 80;
server_name SERVER_NAME;
# HTTP > HTTPS #
return 301 https://$server_name$request_uri;
}
##
# Configure Red with SSL
#
# All requests are routed to the front controller
# except for certain known file types like images, css, etc.
# Those are served statically whenever possible with a
# fall back to the front controller (needed for avatars, for example)
##
server {
listen 443 ssl;
server_name SERVER_NAME;
ssl_certificate /etc/letsencrypt/live/SERVER_NAME/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/SERVER_NAME/privkey.pem;
ssl_session_timeout 5m;
# DO WE NEED TO REVIEW THE FOLLOWING SETTINGS?
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS;
ssl_prefer_server_ciphers on;
fastcgi_param HTTPS on;
charset utf-8;
root INSTALL_PATH;
index index.php;
access_log /var/log/nginx/SERVER_LOG;
#Uncomment the following line to include a standard configuration file
#Note that the most specific rule wins and your standard configuration
#will therefore *add* to this file, but not override it.
#include standard.conf
# allow uploads up to 20MB in size
client_max_body_size 20m;
client_body_buffer_size 128k;
include mime.types;
# rewrite to front controller as default rule
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?req=$1;
}
}
# make sure webfinger and other well known services aren't blocked
# by denying dot files and rewrite request to the front controller
location ^~ /.well-known/ {
allow all;
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?req=$1;
}
}
# statically serve these file types when possible
# otherwise fall back to front controller
# allow browser to cache them
# added .htm for advanced source code editor library
# location ~* \.(jpg|jpeg|gif|png|ico|css|js|htm|html|map|ttf|woff|woff2|svg)$ {
# expires 30d;
# try_files $uri /index.php?req=$uri&$args;
# }
# SHOULD WE UNCOMMENT THE ABOVE LINES ?
# block these file types
location ~* \.(tpl|md|tgz|log|out)$ {
deny all;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
# or a unix socket
location ~* \.php$ {
# IS THE FOLLOWING STILL RELEVANT AS OF AUGUST 2020?
# Zero-day exploit defense.
# http://forum.nginx.org/read.php?2,88845,page=3
# Won't work properly (404 error) if the file is not stored on this
# server, which is entirely possible with php-fpm/php-fcgi.
# Comment the 'try_files' line out if you set up php-fpm/php-fcgi on
# another machine. And then cross your fingers that you won't get hacked.
try_files $uri =404;
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# With php5-cgi alone:
# fastcgi_pass 127.0.0.1:9000;
# With php-fpm:
fastcgi_pass unix:/var/run/php/php-fpm.sock;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# include adminer configuration
include /etc/nginx/snippets/adminer-nginx.inc;
# deny access to all dot files
location ~ /\. {
deny all;
}
#deny access to store
location ~ /store {
deny all;
}
}

View file

@ -0,0 +1,178 @@
###############################################
### MANDATORY - database password #############
#
# Please give your database password
# It is better to not use blanks inside the password.
# Example: db_pass=pass_word_with_no_blanks_in_it
db_pass=
###############################################
### MANDATORY - let's encrypt #################
#
# Encrypted communication via secure HTTP (HTTPS)is required.
# This script automates installation of an SSL certificate from
# Let's Encrypt (https://letsencrypt.org)
#
# Please give the domain name of your website
#
# Example: my.cooldomain.org
# Example: cooldomain.org
#
# You might use "localhost" for a LOCAL TEST installation.
# This is usefull if you want to debug the server inside a VM.
#
# Example: localhost
#
# Email is optional if you use "localhost".
#
#
le_domain=
le_email=
###############################################
### OPTIONAL - Webserver choice ###############
#
# Please indicate if you want to choose Nginx
# or Apache as your web server
#
# Valid strings are nginx or apache (lower case),
# any other will stop the setup script.
#
webserver=apache
###############################################
### OPTIONAL - selfHOST - dynamic IP address ##
#
# 1. Register a domain at selfhost.de
# - choose offer "DOMAIN dynamisch" 1,50€/mon at 04/2019
# 2. Get your configuration for dynamic IP update
# - Log in at selfhost.de
# - go to "DynDNS Accounte"
# - klick "Details" of your (freshly) registered domain
# - You will find the configuration there
# - Benutzername (user name) > use this for "selfhost_user="
# - Passwort (pass word) > use this for "selfhost_pass="
#
#
selfhost_user=
selfhost_pass=
###############################################
### OPTIONAL - FreeDNS - dynamic IP address ###
#
# Please give the alpha-numeric-key of freedns
#
# Get a free subdomain from freedns and use it for your dynamic ip address
# Documentation under http://www.techjawab.com/2013/06/setup-dynamic-dns-dyndns-for-free-on.html
#
# - Register for a Free domain at http://freedns.afraid.org/signup/
# - WATCH THIS: Make sure you choose a domain with as less subdomains as
# possible. Why? Let's encrpyt issues a limited count of certificates each
# day. Possible other users of this domain will try to issue a certificate
# at the same day.
# - Logon to FreeDNS (where you just registered)
# - Goto http://freedns.afraid.org/dynamic/
# - Right click on "Direct Link" and copy the URL and paste it somewhere.
# - You should notice a large and unique alpha-numeric key in the URL
#
# http://freedns.afraid.org/dynamic/update.php?alpha-numeric-key
#
# Provided your url from freedns is
#
# http://freedns.afraid.org/dynamic/update.php?U1Z6aGt2R0NzMFNPNWRjbWxxZGpsd093OjE1Mzg5NDE5
#
# Then you have to provide
#
# freedns_key=U1Z6aGt2R0NzMFNPNWRjbWxxZGpsd093OjE1Mzg5NDE5
#
#
freedns_key=
###############################################
### OPTIONAL - Backup to external device ######
#
# The script can use an external device for the daily backup.
# The file system of the device (USB stick for example) must be compatible with
#
# - encrypted LUKS + ext4, or
# - ext4
#
# You should test to mount the device before you run the script
# (hubzilla-setup.sh).
# How to find your (pluged-in) devices?
#
# fdisk -l
#
# Provided your device was listed as is /dev/sdb1. You could check with:
#
# blkid | grep /dev/sdb1
#
# Try to decrypt
# (You might install cryptsetup befor using apt-get install.
#
# apt-get install cryptsetup
# cryptsetup luksOpen /dev/sdb1 cryptobackup
#
# Try to mount
# You might create the directory /media/hubzilla_backup it it does not exist
# using mkdir.
#
# mkdir /media/hubzilla_backup
# mount /dev/mapper/cryptobackup /media/hubzilla_backup
#
# Unmounting device goes like this
#
# umount /media/hubzilla_backup
# cryptsetup luksClose cryptobackup
#
# To check if still mounted
#
# lsof /media/hubzilla_backup
#
# If you leave the following parameters
#
# - "backup_device_name" and
# - "backup_device_pass"
#
# empty the script will create daily backups on the internal disk (which could
# save you as well).
#
# Example: backup_device_name=/dev/sdc1
#
# Leave "backup_device_pass=" empty if the external device is not encrypted.
#
backup_device_name=
backup_device_pass=
###############################################
### OPTIONAL - do not mess with things below ##
# (...if you are not certain)
#
# Usually you are done here
# Everything below is OPTIONAL
#
###############################################
#
# Database for your hub/instance
# If left empty, both your database and user will be named streams (name of the repository)
# Use custom name, at least fo the database, if you plan to run more than one hub/instance on the same server
#
website_db_name=
website_db_user=
website_db_pass=$db_pass
#
#
# Password for package mysql-server
# Example: mysqlpass=aberhallo
# Example: mysqlpass="aber hallo has blanks in it"
#
mysqlpass=$db_pass
# Password for package phpmyadmin
# Example: phpmyadminpass=aberhallo
# Example: phpmyadminpass="aber hallo has blanks in it"
phpmyadminpass=$db_pass

826
.homeinstall/server-setup.sh Executable file
View file

@ -0,0 +1,826 @@
#!/bin/bash
#
# How to use
# ----------
#
# This file automates the installation of your website using the Streams repository
# (https://codeberg.org/streams/streams)
# under Debian Linux "Bullseye"
#
# 1) Copy the file "server-config.txt.template" to "server-config.txt"
# Follow the instuctions there
#
# 2) Switch to user "root" by typing "su -"
#
# 3) Run with "./server-setup.sh"
# If this fails check if you can execute the script.
# - To make it executable type "chmod +x server-setup.sh"
# - or run "bash server-setup.sh"
#
#
# What does this script do basically?
# -----------------------------------
#
# This file automates the installation of a Nomad/ActivityPub federation capable website
# under Debian Linux. It will:
# - install
# * apache or nginx webserver,
# * php (adding sury repository to get php 8.* on Debian 11),
# * composer
# * mariadb - the database your website,
# * adminer,
# * git to download and update addons
# - configure cron
# * "Run.php" for regular background processes of your website
# * "apt-get update" and "apt-get dist-upgrade" and "apt-get autoremove" to keep linux up-to-date
# * optionally run command to keep the IP up-to-date > DynDNS provided by selfHOST.de or freedns.afraid.org
# * optionally backup your server's database and files (rsync)
# - run letsencrypt to create, register and use a certifacte for https
#
#
# Discussion
# ----------
#
# Security - password is the same for mysql-server, phpmyadmin and your hub/instance db
# - The script runs into installation errors for phpmyadmin if it uses
# different passwords. For the sake of simplicity one single password.
#
# Daily backup
# ------------
#
# The installation
# - writes a shell script in /var/www/
# - creates a daily cron that runs this script
#
# The script makes a (daily) backup of all relevant files
# - /var/lib/mysql/ > database
# - /var/www/ > hubzilla/zap/misty from git repository
# - /etc/letsencrypt/ > certificates
#
# The backup will be written on an external disk compatible to LUKS+ext4 (see server-config.txt)
#
# How to restore from backup
# --------------------------
#
# (Some explanations here would certainly be useful)
#
#
# Credits
# -------
#
# The script is based on Thomas Willinghams script "debian-setup.sh"
# which he used to install the red#matrix.
#
# The documentation for bash is here
# https://www.gnu.org/software/bash/manual/bash.html
#
function check_sanity {
# Do some sanity checking.
print_info "Sanity check..."
if [ $(/usr/bin/id -u) != "0" ]
then
die 'Must be run by root user'
fi
if [ -f /etc/lsb-release ]
then
die "Distribution is not supported"
fi
if [ ! -f /etc/debian_version ]
then
die "Debian is supported only"
fi
if ! grep -q 'Linux 11' /etc/issue
then
die "Linux 11 (bullseye) is supported only"
fi
}
function check_config {
print_info "config check..."
# Check for required parameters
if [ -z "$db_pass" ]
then
die "db_pass not set in $configfile"
fi
if [ -z "$le_domain" ]
then
die "le_domain not set in $configfile"
fi
# backup is important and should be checked
if [ -n "$backup_device_name" ]
then
if [ ! -d "$backup_mount_point" ]
then
mkdir "$backup_mount_point"
fi
device_mounted=0
if fdisk -l | grep -i "$backup_device_name.*linux"
then
print_info "ok - filesystem of external device is linux"
if [ -n "$backup_device_pass" ]
then
echo "$backup_device_pass" | cryptsetup luksOpen $backup_device_name cryptobackup
if mount /dev/mapper/cryptobackup /media/server_backup
then
device_mounted=1
print_info "ok - could encrypt and mount external backup device"
umount /media/server_backup
else
print_warn "backup to external device will fail because encryption failed"
fi
cryptsetup luksClose cryptobackup
else
if mount $backup_device_name /media/server_backup
then
device_mounted=1
print_info "ok - could mount external backup device"
umount /media/server_backup
else
print_warn "backup to external device will fail because mount failed"
fi
fi
else
print_warn "backup to external device will fail because filesystem is either not linux or 'backup_device_name' is not correct in $configfile"
fi
if [ $device_mounted == 0 ]
then
die "backup device not ready"
fi
fi
}
function die {
echo "ERROR: $1" > /dev/null 1>&2
exit 1
}
function update_upgrade {
print_info "updated and upgrade..."
# Run through the apt-get update/upgrade first. This should be done before
# we try to install any package
apt-get -q -y update && apt-get -q -y dist-upgrade
print_info "updated and upgraded linux"
}
function check_install {
if [ -z "`which "$1" 2>/dev/null`" ]
then
# export DEBIAN_FRONTEND=noninteractive ... answers from the package
# configuration database
# - q ... without progress information
# - y ... answer interactive questions with "yes"
# DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -q -y install $2
DEBIAN_FRONTEND=noninteractive apt-get -q -y install $2
print_info "installed $2 installed for $1"
else
print_warn "$2 already installed"
fi
}
function nocheck_install {
# export DEBIAN_FRONTEND=noninteractive ... answers from the package configuration database
# - q ... without progress information
# - y ... answer interactive questions with "yes"
# DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -q -y install $2
# DEBIAN_FRONTEND=noninteractive apt-get --install-suggests -q -y install $1
DEBIAN_FRONTEND=noninteractive apt-get -q -y install $1
print_info "installed $1"
}
function print_info {
echo -n -e '\e[1;34m'
echo -n $1
echo -e '\e[0m'
}
function print_warn {
echo -n -e '\e[1;31m'
echo -n $1
echo -e '\e[0m'
}
function stop_server {
if [ $webserver = "nginx" ]
then
print_info "stopping nginx webserver..."
systemctl stop nginx
elif [ $webserver = "apache" ]
then
print_info "stopping apache webserver..."
systemctl stop apache2
fi
print_info "stopping mysql db..."
systemctl stop mariadb
}
function install_apache {
print_info "installing apache..."
nocheck_install "apache2 apache2-utils"
a2enmod rewrite
systemctl restart apache2
}
function install_nginx {
print_info "installing nginx..."
nocheck_install "nginx"
systemctl restart nginx
}
function add_vhost {
print_info "adding apache vhost"
echo "<VirtualHost *:80>" >> "/etc/apache2/sites-available/${le_domain}.conf"
echo "ServerName ${le_domain}" >> "/etc/apache2/sites-available/${le_domain}.conf"
echo "DocumentRoot $install_path" >> "/etc/apache2/sites-available/${le_domain}.conf"
echo "</VirtualHost>" >> "/etc/apache2/sites-available/${le_domain}.conf"
a2ensite $le_domain
}
function add_nginx_conf {
print_info "adding nginx conf files"
sed "s|SERVER_NAME|${le_domain}|g;s|INSTALL_PATH|${install_path}|g;s|SERVER_LOG|${le_domain}.log|;" nginx-repository.conf.template >> /etc/nginx/sites-available/${le_domain}.conf
ln -s /etc/nginx/sites-available/${le_domain}.conf /etc/nginx/sites-enabled/
if [ ! -f /etc/nginx/snippets/adminer-nginx.inc ]
then
cp adminer-nginx.inc.template /etc/nginx/snippets/adminer-nginx.inc
fi
}
function install_imagemagick {
print_info "installing imagemagick..."
nocheck_install "imagemagick"
}
function install_curl {
print_info "installing curl..."
nocheck_install "curl"
}
function install_wget {
print_info "installing wget..."
nocheck_install "wget"
}
function install_sendmail {
print_info "installing sendmail..."
nocheck_install "sendmail sendmail-bin"
}
function install_sury_repo {
# With Debian 11 (bullseye) we need an extra repo to install php 8.*
if [ ! -f /etc/apt/sources.list.d/sury-php.list ]
then
print_info "installing installing sury-php repository..."
echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | tee /etc/apt/sources.list.d/sury-php.list
wget -qO - https://packages.sury.org/php/apt.gpg | apt-key add -
apt-get update -y
else
print_info "sury-php repository is already installed."
fi
}
function php_version {
# We need to be able to find php version and use it with install_php
$phpversion = $(php -v|grep --only-matching --perl-regexp "(PHP )\d+\.\\d+\.\\d+"|cut -c 5-7)
}
function install_php {
# openssl and mbstring are included in libapache2-mod-php
print_info "installing php..."
if [ $webserver = "nginx" ]
then
nocheck_install "php-fpm php php-pear php-curl php-gd php-mbstring php-xml php-zip"
php_version
sed -i "s/^upload_max_filesize =.*/upload_max_filesize = 100M/g" /etc/php/$phpversion/fpm/php.ini
sed -i "s/^post_max_size =.*/post_max_size = 100M/g" /etc/php/$phpversion/fpm/php.ini
systemctl reload php${phpversion}-fpm
elif [ $webserver = "apache" ]
then
nocheck_install "libapache2-mod-php php php-pear php-curl php-gd php-mbstring php-xml php-zip"
php_version
sed -i "s/^upload_max_filesize =.*/upload_max_filesize = 100M/g" /etc/php/$phpversion/apache2/php.ini
sed -i "s/^post_max_size =.*/post_max_size = 100M/g" /etc/php/$phpversion/apache2/php.ini
fi
}
function install_composer {
# We need to add something here, to check if composer is already installed
EXPECTED_CHECKSUM="$(php -r 'copy("https://composer.github.io/installer.sig", "php://stdout");')"
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
then
>&2 echo 'ERROR: Invalid installer checksum'
rm composer-setup.php
exit 1
fi
php composer-setup.php --quiet
RESULT=$?
rm composer-setup.php
exit $RESULT
# We install Composer globally
mv composer.phar /usr/local/bin/composer
}
function install_mysql {
print_info "installing mysql..."
if [ -z "$mysqlpass" ]
then
die "mysqlpass not set in $configfile"
fi
if type mysql ; then
echo "Yes, mysql is installed"
else
echo "mariadb-server"
nocheck_install "mariadb-server"
systemctl status mariadb
systemctl start mariadb
mysql --user=root <<_EOF_
UPDATE mysql.user SET Password=PASSWORD('${mysqlpass}') WHERE User='root';
DELETE FROM mysql.user WHERE User='';
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
FLUSH PRIVILEGES;
_EOF_
fi
}
function install_adminer {
print_info "installing adminer..."
nocheck_install "adminer"
if [ $webserver = "apache" ]
then
if [ ! -f /etc/adminer/adminer.conf ]
then
echo "Alias /adminer /usr/share/adminer/adminer" > /etc/adminer/adminer.conf
ln -s /etc/adminer/adminer.conf /etc/apache2/conf-available/adminer.conf
else
print_info "file /etc/adminer/adminer.conf exists already"
fi
a2enmod rewrite
if [ ! -f /etc/apache2/apache2.conf ]
then
die "could not find file /etc/apache2/apache2.conf"
fi
sed -i \
"s/AllowOverride None/AllowOverride all/" \
/etc/apache2/apache2.conf
a2enconf adminer
systemctl restart mariadb
systemctl reload apache2
fi
}
function create_website_db {
print_info "creating website's database..."
if [ -z "$website_db_name" ]
then
website_db_name=$install_folder
fi
if [ -z "$website_db_user" ]
then
website_db_user=$install_folder
fi
if [ -z "$website_db_pass" ]
then
die "website_db_pass not set in $configfile"
fi
systemctl restart mariadb
# Make sure we don't write over an already existing database if we install more one website
if [ -z $(mysql -h localhost -u root -p$mysqlpass -e "SHOW DATABASES;" | grep $website_db_name) ]
then
Q1="CREATE DATABASE IF NOT EXISTS $website_db_name;"
Q2="GRANT USAGE ON *.* TO $website_db_user@localhost IDENTIFIED BY '$website_db_pass';"
Q3="GRANT ALL PRIVILEGES ON $website_db_name.* to $website_db_user@localhost identified by '$website_db_pass';"
Q4="FLUSH PRIVILEGES;"
SQL="${Q1}${Q2}${Q3}${Q4}"
mysql -uroot -p$mysqlpass -e "$SQL"
else
die "Can't write over an already existing database!"
fi
}
function run_freedns {
print_info "run freedns (dynamic IP)..."
if [ -z "$freedns_key" ]
then
print_info "freedns was not started because 'freedns_key' is empty in $configfile"
else
if [ -n "$selfhost_user" ]
then
die "You can not use freeDNS AND selfHOST for dynamic IP updates ('freedns_key' AND 'selfhost_user' set in $configfile)"
fi
wget --no-check-certificate -O - http://freedns.afraid.org/dynamic/update.php?$freedns_key
fi
}
function install_run_selfhost {
print_info "install and start selfhost (dynamic IP)..."
if [ -z "$selfhost_user" ]
then
print_info "selfHOST was not started because 'selfhost_user' is empty in $configfile"
else
if [ -n "$freedns_key" ]
then
die "You can not use freeDNS AND selfHOST for dynamic IP updates ('freedns_key' AND 'selfhost_user' set in $configfile)"
fi
if [ -z "$selfhost_pass" ]
then
die "selfHOST was not started because 'selfhost_pass' is empty in $configfile"
fi
if [ ! -d $selfhostdir ]
then
mkdir $selfhostdir
fi
# the old way
# https://carol.selfhost.de/update?username=123456&password=supersafe
#
# the prefered way
wget --output-document=$selfhostdir/$selfhostscript http://jonaspasche.de/selfhost-updater
echo "router" > $selfhostdir/device
echo "$selfhost_user" > $selfhostdir/user
echo "$selfhost_pass" > $selfhostdir/pass
bash $selfhostdir/$selfhostscript update
fi
}
function ping_domain {
print_info "ping domain $domain..."
# Is the domain resolved? Try to ping 6 times à 10 seconds
COUNTER=0
for i in {1..6}
do
print_info "loop $i for ping -c 1 $domain ..."
if ping -c 4 -W 1 $le_domain
then
print_info "$le_domain resolved"
break
else
if [ $i -gt 5 ]
then
die "Failed to: ping -c 1 $domain not resolved"
fi
fi
sleep 10
done
sleep 5
}
function configure_cron_freedns {
print_info "configure cron for freedns..."
if [ -z "$freedns_key" ]
then
print_info "freedns is not configured because freedns_key is empty in $configfile"
else
# Use cron for dynamich ip update
# - at reboot
# - every 30 minutes
if [ -z "`grep 'freedns.afraid.org' /etc/crontab`" ]
then
echo "@reboot root http://freedns.afraid.org/dynamic/update.php?$freedns_key > /dev/null 2>&1" >> /etc/crontab
echo "*/30 * * * * root wget --no-check-certificate -O - http://freedns.afraid.org/dynamic/update.php?$freedns_key > /dev/null 2>&1" >> /etc/crontab
else
print_info "cron for freedns was configured already"
fi
fi
}
function configure_cron_selfhost {
print_info "configure cron for selfhost..."
if [ -z "$selfhost_user" ]
then
print_info "selfhost is not configured because selfhost_key is empty in $configfile"
else
# Use cron for dynamich ip update
# - at reboot
# - every 5 minutes
if [ -z "`grep 'selfhost-updater.sh' /etc/crontab`" ]
then
echo "@reboot root bash /etc/selfhost/selfhost-updater.sh update > /dev/null 2>&1" >> /etc/crontab
echo "*/5 * * * * root /bin/bash /etc/selfhost/selfhost-updater.sh update > /dev/null 2>&1" >> /etc/crontab
else
print_info "cron for selfhost was configured already"
fi
fi
}
function install_letsencrypt {
print_info "installing let's encrypt ..."
# check if user gave domain
if [ -z "$le_domain" ]
then
die "Failed to install let's encrypt: 'le_domain' is empty in $configfile"
fi
if [ -z "$le_email" ]
then
die "Failed to install let's encrypt: 'le_email' is empty in $configfile"
fi
if [ $webserver = "nginx" ]
then
nocheck_install "certbot"
print_info "run certbot..."
systemctl stop nginx
certbot certonly --standalone -d $le_domain -m $le_email --agree-tos --non-interactive
systemctl start nginx
elif [ $webserver = "apache" ]
then
nocheck_install "certbot python-certbot-apache"
print_info "run certbot ..."
certbot --apache -w $install_path -d $le_domain -m $le_email --agree-tos --non-interactive --redirect --hsts --uir
service apache2 restart
fi
}
function check_https {
print_info "checking httpS > testing ..."
url_https=https://$le_domain
wget_output=$(wget -nv --spider --max-redirect 0 $url_https)
if [ $? -ne 0 ]
then
print_warn "check not ok"
else
print_info "check ok"
fi
}
function repo_name {
# We keep this in case the repository is forked in the future
if git remote -v | grep -i "origin.*streams.*"
then
repository=streams
# elif git remote -v | grep -i "origin.*fork_1.*"
# then
# repository=fork_1
# elif git remote -v | grep -i "origin.*fork_2.*"
# then
# repository=fork_2
else
die "this script is not usable with this repository"
fi
}
function install_website {
# We'll also keep things here for future forks
print_info "installing addons..."
cd $install_path/
if [ $repository = "streams" ]
then
print_info "Streams"
util/add_addon_repo https://codeberg.org/streams/streams-addons.git zaddons
# elif [ $repository = "fork_1" ]
# then
# print_info "Fork_1"
# util/add_addon_repo ** REPOSITORY HERE **
# elif [ $repository = "fork_2" ]
# then
# print_info "Fork_2"
# util/add_addon_repo **REPOSITORY HERE **
else
die "no addons can be installed for this repository"
fi
mkdir -p "cache/smarty3"
mkdir -p "store"
chmod -R 777 store
touch .htconfig.php
chmod ou+w .htconfig.php
cd /var/www/
chown -R www-data:www-data $install_path
chown root:www-data $install_path/
chown root:www-data $install_path/.htaccess
chmod 0644 $install_path/.htaccess
print_info "installed addons"
}
function install_rsync {
print_info "installing rsync..."
nocheck_install "rsync"
}
function install_cryptosetup {
print_info "installing cryptsetup..."
nocheck_install "cryptsetup"
}
function configure_daily_update {
echo "#!/bin/sh" >> /var/www/$daily_update
echo "#" >> /var/www/$daily_update
echo "# update of $le_domain federation capable website" >> /var/www/$daily_update
echo "echo \"\$(date) - updating core and addons...\"" >> /var/www/$daily_update
echo "echo \"reaching git repository for $le_domain $repository hub/instance...\"" >> /var/www/$daily_update
echo "(cd $install_path ; util/udall)" >> /var/www/$daily_update
echo "chown -R www-data:www-data $install_path # make all accessible for the webserver" >> /var/www/$daily_update
if [ $webserver = "apache" ]
then
echo "chown root:www-data $install_path/.htaccess" >> /var/www/$daily_update
echo "chmod 0644 $install_path/.htaccess # www-data can read but not write it" >> /var/www/$daily_update
fi
chmod a+x /var/www/$daily_update
}
function configure_cron_daily {
print_info "configuring cron..."
# every 10 min for poller.php
if [ -z "`grep '$install_path.*Run.php' /etc/crontab`" ]
then
echo "*/10 * * * * www-data cd $install_path; php Code/Daemon/Run.php Cron >> /dev/null 2>&1" >> /etc/crontab
fi
# Run external script daily at 05:30
# - stop apache/nginx and mysql-server
# - renew the certificate of letsencrypt
# - backup db, files ($install_path), certificates if letsencrypt
# - update repository core and addon
# - update and upgrade linux
# - reboot is done by "shutdown -h now" because "reboot" hangs sometimes depending on the system
echo "#!/bin/sh" > /var/www/$cron_job
echo "#" >> /var/www/$cron_job
echo "echo \" \"" >> /var/www/$cron_job
echo "echo \"+++ \$(date) +++\"" >> /var/www/$cron_job
echo "echo \" \"" >> /var/www/$cron_job
echo "echo \"\$(date) - stopping $webserver and mysql...\"" >> /var/www/$cron_job
if [ $webserver = "nginx" ]
then
echo "systemctl stop nginx" >> /var/www/$cron_job
elif [ $webserver = "apache" ]
then
echo "service apache2 stop" >> /var/www/$cron_job
fi
echo "/etc/init.d/mysql stop # to avoid inconsistencies" >> /var/www/$cron_job
echo "#" >> /var/www/$cron_job
echo "echo \"\$(date) - renew certificate...\"" >> /var/www/$cron_job
echo "certbot renew --noninteractive" >> /var/www/$cron_job
echo "#" >> /var/www/$cron_job
echo "# backup" >> /var/www/$cron_job
echo "echo \"\$(date) - try to mount external device for backup...\"" >> /var/www/$cron_job
echo "backup_device_name=$backup_device_name" >> /var/www/$cron_job
echo "backup_device_pass=$backup_device_pass" >> /var/www/$cron_job
echo "backup_mount_point=$backup_mount_point" >> /var/www/$cron_job
echo "device_mounted=0" >> /var/www/$cron_job
echo "if [ -n \"\$backup_device_name\" ]" >> /var/www/$cron_job
echo "then" >> /var/www/$cron_job
echo " if blkid | grep $backup_device_name" >> /var/www/$cron_job
echo " then" >> /var/www/$cron_job
if [ -n "$backup_device_pass" ]
then
echo " echo \"decrypting backup device...\"" >> /var/www/$cron_job
echo " echo "\"$backup_device_pass\"" | cryptsetup luksOpen $backup_device_name cryptobackup" >> /var/www/$cron_job
fi
echo " if [ ! -d $backup_mount_point ]" >> /var/www/$cron_job
echo " then" >> /var/www/$cron_job
echo " mkdir $backup_mount_point" >> /var/www/$cron_job
echo " fi" >> /var/www/$cron_job
echo " echo \"mounting backup device...\"" >> /var/www/$cron_job
if [ -n "$backup_device_pass" ]
then
echo " if mount /dev/mapper/cryptobackup $backup_mount_point" >> /var/www/$cron_job
else
echo " if mount $backup_device_name $backup_mount_point" >> /var/www/$cron_job
fi
echo " then" >> /var/www/$cron_job
echo " device_mounted=1" >> /var/www/$cron_job
echo " echo \"device $backup_device_name is now mounted. Starting backup...\"" >> /var/www/$cron_job
echo " rsync -a --delete /var/lib/mysql/ /media/repository_backup/mysql" >> /var/www/$cron_job
echo " rsync -a --delete /var/www/ /media/repository_backup/www" >> /var/www/$cron_job
echo " rsync -a --delete /etc/letsencrypt/ /media/repository_backup/letsencrypt" >> /var/www/$cron_job
echo " echo \"\$(date) - disk sizes...\"" >> /var/www/$cron_job
echo " df -h" >> /var/www/$cron_job
echo " echo \"\$(date) - db size...\"" >> /var/www/$cron_job
echo " du -h $backup_mount_point | grep mysql/repository" >> /var/www/$cron_job
echo " echo \"unmounting backup device...\"" >> /var/www/$cron_job
echo " umount $backup_mount_point" >> /var/www/$cron_job
echo " else" >> /var/www/$cron_job
echo " echo \"failed to mount device $backup_device_name\"" >> /var/www/$cron_job
echo " fi" >> /var/www/$cron_job
if [ -n "$backup_device_pass" ]
then
echo " echo \"closing decrypted backup device...\"" >> /var/www/$cron_job
echo " cryptsetup luksClose cryptobackup" >> /var/www/$cron_job
fi
echo " fi" >> /var/www/$cron_job
echo "fi" >> /var/www/$cron_job
echo "if [ \$device_mounted == 0 ]" >> /var/www/$cron_job
echo "then" >> /var/www/$cron_job
echo " echo \"device could not be mounted $backup_device_name. No backup written.\"" >> /var/www/$cron_job
echo "fi" >> /var/www/$cron_job
echo "#" >> /var/www/$cron_job
echo "echo \"\$(date) - db size...\"" >> /var/www/$cron_job
echo "du -h /var/lib/mysql/ | grep mysql/" >> /var/www/$cron_job
echo "#" >> /var/www/$cron_job
echo "cd /var/www" >> /var/www/$cron_job
echo "for f in *-daily.sh; do \"./\${f}\"; done" >> /var/www/$cron_job
echo "echo \"\$(date) - updating linux...\"" >> /var/www/$cron_job
echo "apt-get -q -y update && apt-get -q -y dist-upgrade && apt-get -q -y autoremove # update linux and upgrade" >> /var/www/$cron_job
echo "echo \"\$(date) - Backup and update finished. Rebooting...\"" >> /var/www/$cron_job
echo "#" >> /var/www/$cron_job
echo "shutdown -r now" >> /var/www/$cron_job
chmod a+x /var/www/$cron_job
# If global cron job does not exist we add it to /etc/crontab
if grep -q $cron_job /etc/crontab
then
echo "cron job already in /etc/crontab"
else
echo "30 05 * * * root /bin/bash /var/www/$cron_job >> /var/www/daily-updates.log 2>&1" >> /etc/crontab
echo "0 0 1 * * root rm /var/www/daily-updates.log" >> /etc/crontab
fi
# This is active after either "reboot" or cron reload"
systemctl restart cron
print_info "configured cron for updates/upgrades"
}
########################################################################
# START OF PROGRAM
########################################################################
export PATH=/bin:/usr/bin:/sbin:/usr/sbin
check_sanity
repo_name
print_info "We're installing a website using the $repository repository"
install_path="$(dirname "$(pwd)")"
install_folder="$(basename $install_path)"
# Read config file edited by user
configfile=server-config.txt
source $configfile
selfhostdir=/etc/selfhost
selfhostscript=selfhost-updater.sh
cron_job="cron_job.sh"
daily_update="${le_domain}-daily.sh"
backup_mount_point="/media/repository_backup"
#set -x # activate debugging from here
check_config
stop_server
update_upgrade
install_curl
install_wget
install_sendmail
install_sury_repo
if [ $webserver = "nginx" ]
then
install_nginx
elif [ $webserver = "apache" ]
then
install_apache
else
die "Failed to install a Web server: 'webserver' not set to \"apache\" or \"nginx\" in $configfile"
fi
install_imagemagick
install_php
if [ $webserver = "nginx" ]
then
add_nginx_conf
elif [ $webserver = "apache" ]
then
if [ "$install_path" != "/var/www/html" ]
then
add_vhost
fi
fi
install_composer
install_mysql
install_adminer
create_website_db
run_freedns
install_run_selfhost
ping_domain
configure_cron_freedns
configure_cron_selfhost
if [ "$le_domain" != "localhost" ]
then
install_letsencrypt
check_https
else
print_info "is localhost - skipped installation of letsencrypt and configuration of apache for https"
fi
install_website
configure_daily_update
configure_cron_daily
if [ "$le_domain" != "localhost" ]
then
install_cryptosetup
install_rsync
else
print_info "is localhost - skipped installation of cryptosetup"
fi
#set +x # stop debugging from here