#!/bin/bash # # .---. . . # | | | # |--- .--. .-. .-. .-.| .-. .--.--. |.-. .-. .--. .-. # | | (.-' (.-' ( | ( )| | | | )( )| | (.-' # ' ' --' --' -' - -' ' ' -' -' -' ' - --' # # Freedom in the Cloud # # Setup functions # # License # ======= # # Copyright (C) 2014-2016 Bob Mottram # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . if [ ! $PROJECT_NAME ]; then PROJECT_NAME='freedombone' fi DEFAULT_DOMAIN_NAME= DEFAULT_DOMAIN_CODE= MY_USERNAME= if [ ! $SYSTEM_TYPE ]; then SYSTEM_TYPE="full" fi # An optional configuration file which overrides some of these variables if [ ! $CONFIGURATION_FILE ]; then CONFIGURATION_FILE="$HOME/${PROJECT_NAME}.cfg" fi # Directory where source code is downloaded and compiled INSTALL_DIR=$HOME/build # device name for an attached usb drive USB_DRIVE=/dev/sda1 # Location where the USB drive is mounted to USB_MOUNT=/mnt/usb # Number of days to keep backups for BACKUP_MAX_DAYS=30 # file containing a list of remote locations to backup to # Format: [username@friendsdomain//home/username] [ssh_password] # With the only space character being between the server and the password FRIENDS_SERVERS_LIST=/home/$MY_USERNAME/backup.list export DEBIAN_FRONTEND=noninteractive # used to limit CPU usage CPULIMIT='/usr/bin/cpulimit -l 20 -e' # command to create a git repository CREATE_GIT_PROJECT_COMMAND='create-project' # File which keeps track of what has already been installed COMPLETION_FILE=$HOME/${PROJECT_NAME}-completed.txt # log file where details of remote backups are stored REMOTE_BACKUPS_LOG=/var/log/remotebackups.log # message if something fails to install CHECK_MESSAGE="Check your internet connection, /etc/network/interfaces and /etc/resolv.conf, then delete $COMPLETION_FILE, run 'rm -fR /var/lib/apt/lists/* && apt-get update --fix-missing' and run this script again. If hash sum mismatches persist then try setting $DEBIAN_REPO to a different mirror and also change /etc/apt/sources.list." # Default diffie-hellman key length in bits DH_KEYLENGTH=2048 function detect_usb_drive { # sets to the highest available drive letter # which is likely to be the last drive connected read_config_param USB_DRIVE partition_number='1' if [[ "$1" == "nopath" ]]; then partition_number='' fi if [ -b /dev/sdb${partition_number} ]; then USB_DRIVE=/dev/sdb${partition_number} fi if [ -b /dev/sdc${partition_number} ]; then USB_DRIVE=/dev/sdc${partition_number} fi if [ -b /dev/sdd${partition_number} ]; then USB_DRIVE=/dev/sdd${partition_number} fi if [ -b /dev/sde${partition_number} ]; then USB_DRIVE=/dev/sde${partition_number} fi if [ -b /dev/sdf${partition_number} ]; then USB_DRIVE=/dev/sdf${partition_number} fi if [ -b /dev/sdg${partition_number} ]; then USB_DRIVE=/dev/sdg${partition_number} fi if [ -b /dev/sdh${partition_number} ]; then USB_DRIVE=/dev/sdh${partition_number} fi write_config_param USB_DRIVE "$USB_DRIVE" } function running_as_root { if [[ $EUID != 0 ]] ; then echo "0" else echo "1" fi } function reset_usb_devices { for xhci in /sys/bus/pci/drivers/?hci-pci ; do if ! cd $xhci ; then return fi echo "Resetting devices from $xhci..." for i in ????:??:??.? ; do echo -n "$i" > unbind echo -n "$i" > bind done done udevadm control --reload-rules } function initial_setup { if [[ $(is_completed $FUNCNAME) == "1" ]]; then return fi apt-get -yq remove --purge apache* apt-get -yq dist-upgrade apt-get -yq install ca-certificates apt-get -yq install apt-utils apt-get -yq install cryptsetup libgfshare-bin obnam sshpass wget avahi-daemon apt-get -yq install avahi-utils avahi-discover connect-proxy openssh-server apt-get -yq install sudo git dialog build-essential avahi-daemon avahi-utils apt-get -yq install avahi-discover avahi-autoipd iptables dnsutils net-tools apt-get -yq install network-manager iputils-ping libnss-mdns libnss-myhostname apt-get -yq install libnss-gw-name nano man ntp locales locales-all debconf apt-get -yq install wireless-tools wpasupplicant usbutils cryptsetup zsh apt-get -yq install pinentry-curses eatmydata iotop bc grub2 hostapd haveged apt-get -yq install cpulimit if [ ! -d $INSTALL_DIR ]; then mkdir -p $INSTALL_DIR fi mark_completed $FUNCNAME } function admin_user_sudo { if ! grep -q "$MY_USERNAME ALL=(ALL) ALL" $rootdir/etc/sudoers; then echo "$MY_USERNAME ALL=(ALL) ALL" >> $rootdir/etc/sudoers fi } function search_for_attached_usb_drive { # If a USB drive is attached then search for email, # gpg, ssh keys and emacs configuration if [[ $(is_completed $FUNCNAME) == "1" ]]; then return fi detect_usb_drive if [ -b $USB_DRIVE ]; then if [ ! -d $USB_MOUNT ]; then echo $'Mounting USB drive' mkdir $USB_MOUNT mount $USB_DRIVE $USB_MOUNT fi if [ -d $USB_MOUNT/.gnupg ]; then echo $'Importing GPG keyring' cp -r $USB_MOUNT/.gnupg /home/$MY_USERNAME chown -R $MY_USERNAME:$MY_USERNAME /home/$MY_USERNAME/.gnupg GPG_KEYS_IMPORTED="yes" if [ ! -f /home/$MY_USERNAME/.gnupg/secring.gpg ]; then echo $'GPG files did not copy' exit 73529 fi fi if [ -f $USB_MOUNT/private_key.gpg ]; then echo $'GPG private key found on USB drive' MY_GPG_PRIVATE_KEY=$USB_MOUNT/private_key.gpg fi if [ -f $USB_MOUNT/public_key.gpg ]; then echo $'GPG public key found on USB drive' MY_GPG_PUBLIC_KEY=$USB_MOUNT/public_key.gpg fi if [ -f $USB_MOUNT/letsencrypt ]; then echo $'Copying letsencrypt keys"' cp -r $USB_MOUNT/letsencrypt /etc fi if [ -d $USB_MOUNT/.ssh ]; then echo $'Importing ssh keys' cp -r $USB_MOUNT/.ssh /home/$MY_USERNAME chown -R $MY_USERNAME:$MY_USERNAME /home/$MY_USERNAME/.ssh # for security delete the ssh keys from the usb drive if [ ! -f /home/$MY_USERNAME/.ssh/id_rsa ]; then echo $'ssh files did not copy' exit 8 fi fi if [ -f $USB_MOUNT/.emacs ]; then echo $'Importing .emacs file' cp -f $USB_MOUNT/.emacs /home/$MY_USERNAME/.emacs chown $MY_USERNAME:$MY_USERNAME /home/$MY_USERNAME/.emacs fi if [ -d $USB_MOUNT/.emacs.d ]; then echo $'Importing .emacs.d directory' cp -r $USB_MOUNT/.emacs.d /home/$MY_USERNAME chown -R $MY_USERNAME:$MY_USERNAME /home/$MY_USERNAME/.emacs.d fi if [ -d $USB_MOUNT/ssl ]; then echo $'Importing SSL certificates' cp -r $USB_MOUNT/ssl/* /etc/ssl chmod 640 /etc/ssl/certs/* chmod 400 /etc/ssl/private/* # change ownership of some certificates if [ -d /etc/prosody ]; then chown prosody:prosody /etc/ssl/private/xmpp.* chown prosody:prosody /etc/ssl/certs/xmpp.* fi if [ -d /etc/dovecot ]; then chown root:dovecot /etc/ssl/certs/dovecot.* chown root:dovecot /etc/ssl/private/dovecot.* fi if [ -f /etc/ssl/private/exim.key ]; then cp /etc/ssl/private/exim.key /etc/exim4 cp /etc/ssl/certs/exim.crt /etc/exim4 cp /etc/ssl/certs/exim.dhparam /etc/exim4 chown root:Debian-exim /etc/exim4/exim.key /etc/exim4/exim.crt /etc/exim4/exim.dhparam chmod 640 /etc/exim4/exim.key /etc/exim4/exim.crt /etc/exim4/exim.dhparam fi fi if [ -d $USB_MOUNT/personal ]; then echo $'Importing personal directory' cp -r $USB_MOUNT/personal /home/$MY_USERNAME chown -R $MY_USERNAME:$MY_USERNAME /home/$MY_USERNAME/personal fi else if [ -d $USB_MOUNT ]; then umount $USB_MOUNT rm -rf $USB_MOUNT fi echo $'No USB drive attached' fi mark_completed $FUNCNAME } function mark_admin_user_account { set_completion_param "Admin user" "$MY_USERNAME" } function remove_instructions_from_motd { sed -i '/## /d' /etc/motd } function remove_default_user { # make sure you don't use the default user account if [[ $MY_USERNAME == "debian" ]]; then echo 'Do not use the default debian user account. Create a different user with: adduser [username]' exit 68 fi # remove the default debian user to prevent it from becoming an attack vector if [ -d /home/debian ]; then userdel -r debian echo 'Default debian user account removed' fi } function create_completion_file { if [ ! -f $COMPLETION_FILE ]; then touch $COMPLETION_FILE fi } function upgrade_installation { # TODO echo '' } function setup_firewall { function_check create_completion_file create_completion_file function_check configure_firewall configure_firewall function_check configure_firewall_ping configure_firewall_ping function_check configure_firewall_for_dns configure_firewall_for_dns function_check configure_firewall_for_avahi configure_firewall_for_avahi function_check global_rate_limit global_rate_limit } function setup_utils { read_config_param "PROJECT_REPO" write_config_param "PROJECT_REPO" "$PROJECT_REPO" function_check create_completion_file create_completion_file function_check read_configuration read_configuration function_check check_system_type check_system_type function_check upgrade_installation upgrade_installation function_check set_default_onion_domains set_default_onion_domains function_check locale_setup locale_setup function_check parse_args parse_args function_check check_domains check_domains function_check install_static_network install_static_network function_check remove_default_user remove_default_user function_check setup_firewall setup_firewall function_check create_repo_sources create_repo_sources function_check configure_dns configure_dns function_check initial_setup initial_setup function_check install_tor install_tor #function_check resolve_dns_via_tor #resolve_dns_via_tor function_check install_command_line_browser install_command_line_browser function_check enable_ssh_via_onion enable_ssh_via_onion function_check check_date check_date function_check install_dynamicdns install_dynamicdns function_check randomize_cron randomize_cron function_check create_freedns_updater create_freedns_updater function_check mark_admin_user_account mark_admin_user_account function_check enforce_good_passwords enforce_good_passwords function_check change_login_message change_login_message function_check enable_zram enable_zram function_check random_number_generator random_number_generator function_check set_your_domain_name set_your_domain_name function_check configure_internet_protocol configure_internet_protocol function_check create_git_project create_git_project function_check setup_wifi setup_wifi function_check configure_ssh configure_ssh function_check configure_ssh_onion configure_ssh_onion function_check allow_ssh_to_onion_address allow_ssh_to_onion_address function_check remove_instructions_from_motd remove_instructions_from_motd function_check check_hwrng check_hwrng function_check search_for_attached_usb_drive search_for_attached_usb_drive function_check regenerate_ssh_keys regenerate_ssh_keys function_check create_mirrors create_mirrors function_check create_upgrade_script create_upgrade_script function_check letsencrypt_renewals letsencrypt_renewals function_check install_watchdog_script install_watchdog_script function_check install_avahi install_avahi function_check create_avahi_onion_domains create_avahi_onion_domains #function_check install_atheros_wifi #install_atheros_wifi function_check route_outgoing_traffic_through_tor route_outgoing_traffic_through_tor function_check upgrade_golang upgrade_golang function_check install_tomb install_tomb function_check admin_user_sudo admin_user_sudo } function setup_email { function_check create_completion_file create_completion_file function_check install_email install_email function_check create_procmail create_procmail function_check handle_admin_emails handle_admin_emails function_check spam_filtering spam_filtering function_check configure_imap configure_imap #function_check configure_imap_client_certs #configure_imap_client_certs function_check configure_gpg configure_gpg function_check refresh_gpg_keys refresh_gpg_keys function_check configure_backup_key configure_backup_key function_check install_monkeysphere install_monkeysphere function_check encrypt_incoming_email encrypt_incoming_email function_check encrypt_outgoing_email encrypt_outgoing_email function_check email_client email_client function_check email_archiving email_archiving function_check email_from_address email_from_address function_check create_public_mailing_list create_public_mailing_list #function check create_private_mailing_list #create_private_mailing_list function_check encrypt_all_email encrypt_all_email function_check import_email import_email } function setup_web { function_check create_completion_file create_completion_file function_check install_web_server install_web_server function_check install_web_server_access_control install_web_server_access_control } function upgrade_apps { function_check create_completion_file create_completion_file APPS_COMPLETED=() FILES=/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-* # for all the app scripts for filename in $FILES do app_name=$(echo "${filename}" | awk -F '-app-' '{print $2}') item_in_array "${app_name}" "${APPS_COMPLETED[@]}" if [[ $? != 0 ]]; then function_check app_is_installed if [[ "$(app_is_installed $a)" == "1" ]]; then app_load_variables ${app_name} APPS_COMPLETED+=("${app_name}") function_check upgrade_${app_name} upgrade_${app_name} fi fi done } function setup_apps { is_interactive=$1 function_check create_completion_file create_completion_file function_check detect_installable_apps detect_installable_apps function_check choose_apps_for_variant choose_apps_for_variant "$SYSTEM_TYPE" echo $"System variant: $SYSTEM_TYPE" echo $'The following apps have been selected' echo '' function_check list_chosen_apps list_chosen_apps echo '' function_check upgrade_apps upgrade_apps if [[ $is_interactive == "menuconfig"* ]]; then ${PROJECT_NAME}-addremove add-all if [ ! "$?" = "0" ]; then exit 72524 fi fi if [[ $is_interactive == "noninteractive" || $is_interactive == "headless" ]]; then function_check install_apps install_apps if [ ! $APP_INSTALLED_SUCCESS ]; then echo $'One or more apps failed to install' fi fi } function combine_all_scripts { combined_filename=$1 # initial variables cp $PROJECT_INSTALL_DIR/${PROJECT_NAME}-vars $combined_filename # utilities UTILS_FILES=/usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-* for f in $UTILS_FILES do # this removes the first line, which is #!/bin/bash tail -n +2 "$f" >> $combined_filename done # base system BASE_SYSTEM_FILES=/usr/share/${PROJECT_NAME}/base/${PROJECT_NAME}-base-* for f in $BASE_SYSTEM_FILES do tail -n +2 "$f" >> $combined_filename done # apps APP_FILES=/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-* for f in $APP_FILES do tail -n +2 "$f" >> $combined_filename done } # NOTE: deliberately no exit 0