#!/bin/bash set -exo pipefail BLUE_BOLD=$'\e[1;34m' RESET=$'\e[0m' checkpoint=$(cat ./hmn_setup_checkpoint || echo 0) savecheckpoint() { echo $1 > ./hmn_setup_checkpoint } do_as() { sudo -u $1 --preserve-env=PATH bash -s } # Add swap space # https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-20-04 if [ $checkpoint -lt 10 ]; then fallocate -l 1G /swapfile chmod 600 /swapfile mkswap /swapfile swapon /swapfile swapon --show echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab sysctl vm.swappiness=10 sysctl vm.vfs_cache_pressure=50 echo 'vm.swappiness=10' >> /etc/sysctl.conf echo 'vm.vfs_cache_pressure=50' >> /etc/sysctl.conf savecheckpoint 10 fi # Configure Linux users if [ $checkpoint -lt 20 ]; then groupadd --system caddy useradd --system \ --gid caddy \ --shell /bin/bash \ --create-home --home-dir /home/caddy \ caddy groupadd --system hmn useradd --system \ --gid hmn \ --shell /bin/bash \ --create-home --home-dir /home/hmn \ hmn groupadd --system annotations useradd --system \ --gid annotations \ --shell /bin/bash \ --create-home --home-dir /home/annotations \ annotations usermod -a -G annotations hmn savecheckpoint 20 fi # Install important stuff if [ $checkpoint -lt 30 ]; then apt update apt install -y \ build-essential \ libcurl4-openssl-dev byacc flex \ s3cmd savecheckpoint 30 fi # Install Go if [ $checkpoint -lt 40 ]; then wget https://golang.org/dl/go1.17.linux-amd64.tar.gz tar -C /usr/local -xzf go1.17.linux-amd64.tar.gz export PATH=$PATH:/usr/local/go/bin:/root/go/bin echo 'export PATH=$PATH:/usr/local/go/bin:/root/go/bin' >> ~/.bashrc go version do_as hmn <<'SCRIPT' set -euxo pipefail echo 'export PATH=$PATH:/usr/local/go/bin:/home/hmn/go/bin' >> ~/.bashrc go version SCRIPT savecheckpoint 40 fi export PATH=$PATH:/usr/local/go/bin:/root/go/bin # Install Caddy # https://www.digitalocean.com/community/tutorials/how-to-host-a-website-with-caddy-on-ubuntu-18-04 if [ $checkpoint -lt 50 ]; then go install github.com/caddyserver/xcaddy/cmd/xcaddy@v0.1.9 xcaddy build \ --with github.com/caddy-dns/cloudflare \ --with github.com/aksdb/caddy-cgi/v2 mv caddy /usr/bin chown root:root /usr/bin/caddy chmod 755 /usr/bin/caddy savecheckpoint 50 fi # Install Postgres # (instructions at https://www.postgresql.org/download/linux/ubuntu/) if [ $checkpoint -lt 60 ]; then sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - sudo apt-get update sudo apt-get -y install postgresql savecheckpoint 60 fi # Configure Postgres if [ $checkpoint -lt 70 ]; then echo "Enter the password for the HMN postgres user:" sudo -u postgres createuser --createdb --login --pwprompt hmn savecheckpoint 70 fi # Set up the folder structure if [ $checkpoint -lt 80 ]; then set +x do_as hmn <<'SCRIPT' cd ~ mkdir log mkdir bin echo 'export PATH=$PATH:/home/hmn/bin' >> ~/.bashrc SCRIPT savecheckpoint 80 fi # Set up SSH for hmn if [ $checkpoint -lt 81 ]; then set +x do_as hmn <<'SCRIPT' ssh-keygen -t ed25519 -C "beta-server" -N "" -f ~/.ssh/gitlab-hmn git config --global core.sshCommand "ssh -i ~/.ssh/gitlab-hmn" SCRIPT do_as annotations <<'SCRIPT' ssh-keygen -t ed25519 -C "beta-server" -N "" -f ~/.ssh/gitlab-annotation-system ssh-keygen -t ed25519 -C "beta-server" -N "" -f ~/.ssh/gitlab-hmml SCRIPT echo "" echo "Add the following keys as Deploy Keys to the following projects:" echo "" cat /home/hmn/.ssh/gitlab-hmn.pub echo "https://git.handmade.network/hmn/hmn/-/settings/ci_cd#js-deploy-keys-settings" echo "" cat /home/annotations/.ssh/gitlab-annotation-system.pub echo "https://git.handmade.network/Annotation-Pushers/Annotation-System/-/settings/ci_cd#js-deploy-keys-settings" echo "" cat /home/annotations/.ssh/gitlab-hmml.pub echo "https://git.handmade.network/Annotation-Pushers/cinera_handmade.network/-/settings/ci_cd#js-deploy-keys-settings" echo "" echo "Run this script again when you're done - it will continue where it left off." savecheckpoint 81 # This is a special case, where we want to halt the script and allow the # user to perform an action before moving on. exit 0 fi # Test SSH for hmn if [ $checkpoint -lt 82 ]; then do_as hmn <<'SCRIPT' set -euxo pipefail if ! ssh -T -i ~/.ssh/gitlab-hmn git@git.handmade.network; then set +x echo "Copy the following key:" echo "" cat ~/.ssh/gitlab-hmn echo "" echo "Add it as a Deploy Key to the HMN project in GitLab:" echo "" echo " https://git.handmade.network/hmn/hmn/-/settings/ci_cd#js-deploy-keys-settings" echo "" exit 1 fi SCRIPT do_as annotations <<'SCRIPT' if ! ssh -T -i ~/.ssh/gitlab-annotation-system git@git.handmade.network; then set +x echo "Copy the following key:" echo "" cat ~/.ssh/gitlab-annotation-system echo "" echo "Add it as a Deploy Key to this project in GitLab:" echo "" echo " https://git.handmade.network/Annotation-Pushers/Annotation-System/-/settings/ci_cd#js-deploy-keys-settings" echo "" exit 1 fi if ! ssh -T -i ~/.ssh/gitlab-hmml git@git.handmade.network; then set +x echo "Copy the following key:" echo "" cat ~/.ssh/gitlab-hmml echo "" echo "Add it as a Deploy Key to this project in GitLab:" echo "" echo " https://git.handmade.network/Annotation-Pushers/cinera_handmade.network/-/settings/ci_cd#js-deploy-keys-settings" echo "" exit 1 fi SCRIPT savecheckpoint 82 fi # Clone the repo if [ $checkpoint -lt 90 ]; then do_as hmn <<'SCRIPT' set -euxo pipefail cd ~ git clone git@git.handmade.network:hmn/hmn.git SCRIPT savecheckpoint 90 fi # Copy config files to the right places if [ $checkpoint -lt 100 ]; then cp /home/hmn/hmn/server/Caddyfile /home/caddy/Caddyfile cp /home/hmn/hmn/server/caddy.service /etc/systemd/system/caddy.service cp /home/hmn/hmn/server/hmn.service /etc/systemd/system/hmn.service cp /home/hmn/hmn/server/cinera.service /etc/systemd/system/cinera.service chmod 644 /etc/systemd/system/caddy.service chmod 644 /etc/systemd/system/hmn.service chmod 644 /etc/systemd/system/cinera.service cp /home/hmn/hmn/server/logrotate /etc/logrotate.d/hmn cp /home/hmn/hmn/src/config/config.go.example /home/hmn/hmn/src/config/config.go cp /home/hmn/hmn/server/hmn.conf.example /home/hmn/hmn/server/hmn.conf cp /home/hmn/hmn/adminmailer/config.go.example /home/hmn/hmn/adminmailer/config.go cp /home/hmn/hmn/cinera/cinera.conf.sample /home/hmn/hmn/cinera/cinera.conf chown hmn:hmn /home/hmn/hmn/src/config/config.go chown hmn:hmn /home/hmn/hmn/server/hmn.conf chown hmn:hmn /home/hmn/hmn/cinera/cinera.conf cp /home/hmn/hmn/server/.s3cfg /home/hmn/.s3cfg chown hmn:hmn /home/hmn/.s3cfg chmod 600 /home/hmn/.s3cfg cp /home/hmn/hmn/server/root.Makefile /root/Makefile systemctl daemon-reload savecheckpoint 100 fi # Set up crons if [ $checkpoint -lt 105 ]; then # See https://stackoverflow.com/a/9625233/1177139 (crontab -l 2>/dev/null; echo "50 4 * * * /home/hmn/hmn/server/backup.sh") | crontab - # TODO: This seems to fail the first time you run it? But then works fine afterward, thanks # to checkpoints. Probably should fix this someday. savecheckpoint 105 fi # Build the site for the first time (despite bad config) if [ $checkpoint -lt 110 ]; then do_as hmn <<'SCRIPT' set -euxo pipefail cd /home/hmn/hmn echo "Building the site for the first time. This may take a while..." go build -v -o /home/hmn/bin/hmn src/main.go SCRIPT echo 'PATH=$PATH:/home/hmn/bin' >> ~/.bashrc source ~/.bashrc savecheckpoint 110 fi cat <<HELP Everything has been successfully installed! ${BLUE_BOLD}===== Next steps =====${RESET} First, make sure you have everything on your path: source ~/.bashrc ${BLUE_BOLD}Edit the Caddy config${RESET} Get an API token from Cloudflare. The token must have the Zone / Zone / Read and Zone / DNS / Edit permissions (as laid out in the following links). https://github.com/caddy-dns/cloudflare https://github.com/libdns/cloudflare Then edit the Caddyfile: vim /home/caddy/Caddyfile Add the Cloudflare token to allow the ACME challenge to succeed, and add the correct domains. (Don't forget to include both the normal and wildcard domains.) Also, in the CGI config, add the name of the Git branch you would like to use when deploying. For example, a deployment of the beta site should use the 'beta' branch. ${BLUE_BOLD}Edit the website config${RESET} Edit the config file using a special make task: make edit-config Fill out everything, then rebuild the site: make build You don't need to deploy the site yet; wait until you've configured everything. ${BLUE_BOLD}Edit HMN environment vars${RESET} First, go to GitLab and add a webhook with a secret. Set it to trigger on push events for the branch you are using for deploys. https://git.handmade.network/hmn/hmn/hooks Then, edit the following file and fill in all the environment vars, including the secret value from the GitLab webhook: /home/hmn/hmn/server/hmn.conf ${BLUE_BOLD}Configure s3cmd${RESET} Edit the following file: /home/hmn/.s3cfg Add the DigitalOcean Spaces credentials, and ensure that the bucket info is correct. ${BLUE_BOLD}Configure Cinera${RESET} Edit the following file, adding the correct domain: /home/hmn/hmn/cinera/cinera.conf ${BLUE_BOLD}Configure the admin mailer${RESET} Fill in the config file and build the mailer: cd /home/hmn/hmn/adminmailer vim config.go go build -o /usr/bin/adminmailer . ${BLUE_BOLD}Download and restore a database backup${RESET} make download-database su hmn cd ~ hmn seedfile <your backup file> hmn migrate ${BLUE_BOLD}Restore static files${RESET} make restore-static-files ${BLUE_BOLD}Set up Cinera${RESET} cd /home/hmn/hmn/cinera ./setup.sh ${BLUE_BOLD}Start up Caddy${RESET} systemctl start caddy ${BLUE_BOLD}Deploy the site!${RESET} make deploy Run 'make' on its own to see all the other tasks available to you! HELP