Install IPFS by script

The latest version of this information is available at https://github.com/ThomasFreedman/ipfs


These are scripts to install IPFS onto Raspberry Pi3 or Pi3+ microcomputers, AND any hardware (laptops, old computers etc) a Debian Linux OS can be installed on. Note that only 64 bit systems are supported.

Potentially almost any Linux OS could be used, however these scripts have only been tested on Debian and Raspberry Pi3 (RPi3 or RPi3+) as written. The Debian Net Installer was used for all non RPi systems.

There are 2 different methods used to install IPFS:

  1. Using the standard Debian package manager (apt / apt-get) configured with the siderus repository
  2. Using a "go" language (golang) approach to install the go language and ipfs-update to install IPFS

Each have their merrits and issues. The golang approach is slower, but provides the ability to obtain the latest IPFS version.

These scripts provide a "grandma just button" to get a base IPFS installation up and running, after the base operating system is installed on the target hardware. Instructions that go thru the setup process for the Raspberry Pi3 (RPi3 or RPi3+) will soon follow. Instructions for the Debian OS installation onto laptops and other hardware are more difficult due to the variation of hardware and BIOSs systems use. There is a multitude of documentation available online to install different Linux OS versions from distributors such as Debian, Mint, Ubuntu etc. I see no reason to duplicate those. There is much more work to be done to build on top of the base OS layer that is a priority.

I wouldn't say installing any OS is easy for grandma. Depending on the chosen OS (and grandma), some are easier than others. The main focus here is getting IPFS installed on a fresh OS installation, not what it takes to get the base OS installed.

Once IPFS is installed, which is what these scripts do with almost no human intervention, the next task to accomplish is getting content off from centralized media platforms and onto IPFS. That requires standards and conventions for pinning, metadata capture and indexing.

Currently there are 4 IPFS installation scripts that automate the steps described on http://sitepins.net/guides/install-ipfs:

  1. **install-ipfs** A new unified installer for all platforms (recommended)
  2. **go-ipfs-amd64** Installer for 64 bit Linux OS (only tested with Debian) using golang
  3. **go-ipfs-rpi3** Installer for golang based installation for RPi3
  4. **siderus-ipfs-rpi3** Installer using siderus apt repository for RPi3

Once you have your base operating system installed, copy one of these scripts to your target system and run it to install IPFS. These are bash shell scripts, and must be run as root or with a sudo prefix. No command line arguments are necessary. They will create an "ipfs" account you can login with, set the maximum space devoted to IPFS storage to 75% of available disk space, and create an init.log file in /home/ipfs/.ipfs/ with the IPFS node hash ID.

The Go language seems to change versions regularly, and it may be necessary to change the version if you see a version is unavailable. I am not aware of a method to install "the latest" version of Go (but latest version of ipfs is possible using go), and if there were it may break the ipfs-update program if it isn't compatible with the latest Go language version.

See the options for the unified installer enter:

$>./install-ipfs [-h | -help]


Script for Installing IPFS

Download directly: install-ipfs

#!/bin/bash

# This script will install IPFS software and establish initial settings.
# This must be executed with root privileges or with sudo.
#
# Options:

usage() {
  echo "None of the following options are required (default values will be used):"
  echo "-a == autostart method, 0 or 1. 0 == systemd (default), 1 == cron @reboot"
  echo "-d == distribution upgrade, 0 or 1. Standard update/upgrade only (default) "
  echo "-g == go version. Default is NoGo. Use 1.10.1 if -g and no option value provided"
  echo "-m == max storage space. Default is 75% of disk. Option value integer in gigabytes"
  echo "-n == install from siderus apt repo. Default, not Go. Invalid if -g is specified"
  echo "-s == Single step / debug. Default is no waiting, non single step / debug mode"
  echo "-h == print this usage info and exit. Also for --help"
}

if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root, or prefix with 'sudo'" ; exit 1 ; fi

# Calculate disk space available for IPFS
FREE=`df --output=avail -B 1 / | tail -n 1` # Free space in bytes on root partition
MAX=`expr $FREE / 1320000000`      # Approximately 75% of free space (in GB)
printf -v STORAGE_MAX %dG $MAX     # The default StorageMax parameter value

AUTO=0                             # Default autostart method 0 == systemd, 1 == cron @reboot
WAIT=0                             # Default value for single step / debug mode (no wait)
DISTUP=0                           # Default value for dist-upgrade (don't do it!)
GOVER=NoGo                         # Default Go language version (Don't use go version)
CONFIG=/home/ipfs/.ipfs/config     # IPFS configuration file

# Determine OpSys (Raspbian or Debian)
OS=`lsb_release -is`
if [[ $OS != "Raspbian" && $OS != "Debian" ]]; then
   echo "$OS Linux detected! This script is for Raspbian or Debian only for now."
   exit 1
fi
if [ $OS == "Raspbian" ]; then
  ARCH=armv6l;
else
  ARCH=amd64;                      # No support for 32 bit systems; should we?
fi

# Make sure we have enhanced getopt -- probably not required for most Linux distros
getopt --test
if [ $? -ne 4 ] then echo "Ouch! getopt not avialable on this system - Bye!"; exit 1; fi

# Read command line options
OPTS=`getopt -o a::dg::m:nsh --long help -name "$0" -- "$@"`
eval set -- "$OPTS"

# extract options and their arguments and set appropriate variables.
while true ; do
    case "$1" in
        -a)
            if [ "$2" != "" ]; then
              AUTO=$2;
              echo "Will use golang version $GOVER"
              shift;
            else
            SYSD=0
            shift
            ;;
        -d)
            DISTUP=1
            shift
            ;;
        -g)
            if [ "$2" != "" ]; then
              GOVER=$2;
              echo "Will use golang version $GOVER"
              shift;
            else
              GOVER=1.10.1
            fi
            shift
            ;;
        -m)
            if [ "$2" != "" ]; then
              if ! [ -z "${2//[0-9]}" ]; then          # Positive number?
                echo "-m requires a positive integer"
                exit 1
              fi
              STORAGE_MAX=$2;
              shift;
            fi
            shift
            ;;
        -n)
            if [ $GOVER ]; then
              echo "Cannot use both -g and -n options!"
              exit 1
            fi
            shift
            break
            ;;
        -h|--help)
            usage()
            exit 0
        *)
            echo "No such option: $1" >&2
            exit 1
            ;;
    esac
done


if [ ! -f ready4ipfs ]; then
  if [ ! ping -q -w 1 -c 1 storage.googleapis.com > /dev/null ]; then
    if [$OS == "Raspbian" ]; then
      # Make sure the system is configured for network access
      echo ""
      echo "The system must be configured, at least to setup networking."
      echo "REBOOT if raspi-config asks, then run this again when rebooted."
      echo "You can just exit raspi-config the second time, don't reboot."
      read -n 1 -p "Press any key to launch the raspi-config utility..." key
      raspi-config
    else
      echo ""
      echo "It doesn't appear the system is online. Make sure networking"
      echo "is operational, then try again. Bye for now!"
      exit -1
    fi
  fi
  echo "Updating the OS (Operating System)..."
  apt-get -y update
  apt-get -y upgrade
  touch ready4ipfs
  if [ $DISTUP == 1 ]; then
    echo ""
    echo "Performing a distribution upgrade, which may bump OS / kernel version..."
    apt-get -y dist-upgrade
    echo ""
    echo "Need to reboot. Afterwards, rerun this script to finish IPFS installation."
    read -n 1 -p "Press ^C to abort, or any other key to reboot..." key
    reboot
  fi
fi

if [ ! -d /home/ipfs ]; then
  echo "Preparing the ipfs user account..."
  if [ ! -d /home/ipfs ]; then useradd -m -s /bin/bash ipfs; fi
  if [ ! -d /home/ipfs/.ipfs ]; then mkdir /home/ipfs/.ipfs; fi
  if [ $GOVER != "NoGo" ]; then
    mkdir /home/ipfs/go
    chown -R ipfs.ipfs /home/ipfs
    echo "source /usr/local/bin/goInit" >> /home/ipfs/.profile  # Sets PATH and GOPATH
  fi
  echo ""
  if [ $WAIT == 1 ]; then read -n 1 -p "Press ^C to exit, any other key to proceed..." key; fi
fi

if [ "$GOVER" == "NoGo" ]; then
  if [ ! -e /etc/apt/sources.list.d/siderus.list ]; then
    echo "Installing credentials for siderus software repository..."
    apt install -y apt-transport-https curl
    curl https://get.siderus.io/key.public.asc | apt-key add -
    echo "deb https://get.siderus.io/ apt/" | tee -a /etc/apt/sources.list.d/siderus.list
    apt update
  fi
else
  if [ ! -e /usr/local/bin/go$GOVER.linux-$ARCH.tar.gz ]; then
    pushd /usr/local/bin
    echo "Installing binary golang version $GOVER from googleapis. Please be patient..."
    wget https://storage.googleapis.com/golang/go$GOVER.linux-$ARCH.tar.gz
    tar -C /usr/local -xzf go$GOVER.linux-$ARCH.tar.gz
    echo 'export GOPATH=/home/$USER/go' >> /usr/local/bin/goInit
    echo 'export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin' > /usr/local/bin/goInit

    echo "export GOPATH=/root/go" >> /root/.profile
    echo "export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin" >> /root/.profile
    popd
    mkdir /root/go
    source /root/.profile
    go version
  else
    echo "No such golang: https://storage.googleapis.com/golang/go$GOVER.linux-$ARCH.tar.gz"
    exit -1
  fi
fi
echo ""
if [ $WAIT == 1 ]; then read -n 1 -p "Press ^C to exit, any other key to proceed..." key; fi

echo "Installing IPFS and supporting packages. Please be patient..."
apt-get -y install tmux ufw
if [ $GOVER == "NoGo" ]; then
  apt-get -y install ipfs
else
  runuser -l ipfs -c 'go get -u github.com/ipfs/ipfs-update'
  runuser -l ipfs -c 'ipfs-update install latest'
fi
runuser -l ipfs -c 'ipfs init > ~/.ipfs/init.log 2>&1'   # Initialize IPFS and log output
apt -y autoremove
echo ""
if [ $WAIT == 1 ]; then read -n 1 -p "Press ^C to exit, any other key to proceed..." key; fi

echo "Opening required firewall ports..."
ufw allow 4001/tcp
ufw allow 22/tcp
echo ""
if [ $WAIT == 1 ]; then read -n 1 -p "Press ^C to exit, any other key to proceed..." key; fi

echo "Setting maximum IPFS storage to $STORAGE_MAX in config file..."
sed -i "s/^\s*\"StorageMax.*$/    ~StorageMax~: ~$STORAGE_MAX~,/g" $CONFIG
sed -i "s/~/\"/g" $CONFIG
echo ""
if [ $WAIT == 1 ]; then read -n 1 -p "Press ^C to exit, any other key to proceed..." key; fi

if [ $AUTO == 0 ]; then  # For some unknown reason this doesn't always work on debian minimal server
  echo "Creating SystemD unit to start IPFS on reboot..."
  (
  cat << SYSD_UNIT
[Unit]
Description=IPFS daemon
After=network.target
[Service]
User=ipfs
LimitNOFILE=65536
Environment="IPFS_FD_MAX=4096"
Environment="IPFS_PATH=/home/ipfs/.ipfs"
ExecStart=/home/ipfs/go/bin/ipfs daemon --enable-namesys-pubsub
Restart=on-failure
[Install]
WantedBy=multi-user.target
SYSD_UNIT
) > /etc/systemd/system/ipfs.service

  systemctl enable ipfs
  systemctl start ipfs

else # Use this alternate way to start service on system start
  echo "#!/bin/bash" > /home/ipfs/autostart.bash
  echo ". /usr/local/bin/goInit" >> /home/ipfs/autostart.bash
  echo "export LimitNOFILE=65536" >> /home/ipfs/autostart.bash   # Might not work as env
  echo "export IPFS_FD_MAX=4096" >> /home/ipfs/autostart.bash
  echo "export IPFS_PATH=/home/ipfs/.ipfs" >> /home/ipfs/autostart.bash
  echo "/home/ipfs/go/bin/ipfs daemon --enable-namesys-pubsub" >> /home/ipfs/autostart.bash
  echo "@reboot ipfs /bin/bash /home/ipfs/autostart.bash" > /etc/cron.d/autoStart
  chmod 755 /etc/cron.d/autoStart
fi

cat /home/ipfs/.ipfs/init.log
echo ""
echo "IPFS is now installed on this system."