diff --git a/create_lxc_base.sh b/create_lxc_base.sh deleted file mode 100755 index 6d1b1ad..0000000 --- a/create_lxc_base.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/bin/bash - -set -eu -cd "$(dirname "$0")" - -bash -c "./stub_lxc_profile.sh --lxd-hostname=$BASE_IMAGE_VM_NAME" - -if lxc list -q --project default | grep -q "$BASE_IMAGE_VM_NAME" ; then - lxc delete -f "$BASE_IMAGE_VM_NAME" --project=default -fi - -# let's download our base image. -if ! lxc image list --format csv --columns l | grep -q "$UBUNTU_BASE_IMAGE_NAME"; then - # if the image if cached locally, import it from disk, otherwise download it from ubuntu - IMAGE_IDENTIFIER=$(find "$SS_JAMMY_PATH" | grep ".qcow2" | head -n1 | cut -d "." -f1) - METADATA_FILE="$SS_JAMMY_PATH/meta-$IMAGE_IDENTIFIER.tar.xz" - IMAGE_FILE="$SS_JAMMY_PATH/$IMAGE_IDENTIFIER.qcow2" - if [ -d "$SS_JAMMY_PATH" ] && [ -f "$METADATA_FILE" ] && [ -f "$IMAGE_FILE" ]; then - lxc image import "$METADATA_FILE" "$IMAGE_FILE" --alias "$UBUNTU_BASE_IMAGE_NAME" - else - # copy the image down from canonical. - lxc image copy "images:$BASE_LXC_IMAGE" "$REMOTE_NAME": --alias "$UBUNTU_BASE_IMAGE_NAME" --public --vm --auto-update - fi -fi - -# If the lxc VM does exist, then we will delete it (so we can start fresh) -if lxc list --format csv -q | grep -q "$UBUNTU_BASE_IMAGE_NAME"; then - # if there's no snapshot, we dispense with the old image and try again. - if ! lxc info "$BASE_IMAGE_VM_NAME" | grep -q "$UBUNTU_BASE_IMAGE_NAME"; then - lxc delete "$BASE_IMAGE_VM_NAME" --force - ssh-keygen -f "$SSH_HOME/known_hosts" -R "$BASE_IMAGE_VM_NAME" - fi -else - # the base image is ubuntu:22.04. - lxc init --profile="$BASE_IMAGE_VM_NAME" "$UBUNTU_BASE_IMAGE_NAME" "$BASE_IMAGE_VM_NAME" --vm --project=default - - # TODO move this sovereign-stack-base construction VM to separate dedicated IP - lxc config set "$BASE_IMAGE_VM_NAME" --project=default - - # for CHAIN in mainnet testnet; do - # for DATA in blocks chainstate; do - # lxc storage volume attach ss-base "$CHAIN-$DATA" "$BASE_IMAGE_VM_NAME" "/home/ubuntu/bitcoin/$DATA" - # done - # done - - lxc start "$BASE_IMAGE_VM_NAME" --project=default - - sleep 15 - while lxc exec "$BASE_IMAGE_VM_NAME" --project=default -- [ ! -f /var/lib/cloud/instance/boot-finished ]; do - sleep 1 - done - - # ensure the ssh service is listening at localhost - lxc exec "$BASE_IMAGE_VM_NAME" --project=default -- wait-for-it -t 100 127.0.0.1:22 - - # # If we have any chaninstate or blocks in our SSME, let's push them to the - # # remote host as a zfs volume that way deployments can share a common history - # # of chainstate/blocks. - # for CHAIN in testnet mainnet; do - # for DATA in blocks chainstate; do - # # if the storage snapshot doesn't yet exist, create it. - # if ! lxc storage volume list ss-base -q --format csv -c n | grep -q "$CHAIN-$DATA/snap0"; then - # DATA_PATH="/home/ubuntu/.ss/cache/bitcoin/$CHAIN/$DATA" - # if [ -d "$DATA_PATH" ]; then - # COMPLETE_FILE_PATH="$DATA_PATH/complete" - # if lxc exec "$BASE_IMAGE_VM_NAME" -- [ ! -f "$COMPLETE_FILE_PATH" ]; then - # lxc file push --recursive --project=default "$DATA_PATH/" "$BASE_IMAGE_VM_NAME""$DATA_PATH/" - # lxc exec "$BASE_IMAGE_VM_NAME" -- su ubuntu - bash -c "echo $(date) > $COMPLETE_FILE_PATH" - # lxc exec "$BASE_IMAGE_VM_NAME" -- chown -R 999:999 "$DATA_PATH/$DATA" - # else - # echo "INFO: it appears as though $CHAIN/$DATA has already been initialized. Continuing." - # fi - # fi - # fi - # done - # done - - # stop the VM and get a snapshot. - lxc stop "$BASE_IMAGE_VM_NAME" --project=default - lxc snapshot "$BASE_IMAGE_VM_NAME" "$UBUNTU_BASE_IMAGE_NAME" --project=default - -fi - -echo "INFO: Publishing '$BASE_IMAGE_VM_NAME' as image '$DOCKER_BASE_IMAGE_NAME'. Please wait." -lxc publish --public "$BASE_IMAGE_VM_NAME/$UBUNTU_BASE_IMAGE_NAME" --project=default --alias="$DOCKER_BASE_IMAGE_NAME" --compression none - -echo "INFO: Success creating the base image. Deleting artifacts from the build process." -lxc delete -f "$BASE_IMAGE_VM_NAME" --project=default - -# # now let's get a snapshot of each of the blocks/chainstate directories. -# for CHAIN in testnet mainnet; do -# for DATA in blocks chainstate; do -# if ! lxc storage volume list ss-base -q --format csv -c n | grep -q "$CHAIN-$DATA/snap0"; then -# echo "INFO: Creating a snapshot 'ss-base/$CHAIN-$DATA/snap0'." -# lxc storage volume snapshot ss-base --project=default "$CHAIN-$DATA" -# fi -# done -# done diff --git a/deploy.sh b/deploy.sh deleted file mode 100755 index 6faa332..0000000 --- a/deploy.sh +++ /dev/null @@ -1,441 +0,0 @@ -#!/bin/bash - -set -e -cd "$(dirname "$0")" - -LATEST_GIT_COMMIT="$(cat ./.git/refs/heads/main)" -export LATEST_GIT_COMMIT="$LATEST_GIT_COMMIT" - -# check to ensure dependencies are met. -for cmd in wait-for-it dig rsync sshfs lxc; do - if ! command -v "$cmd" >/dev/null 2>&1; then - echo "This script requires \"${cmd}\" to be installed. Please run 'install.sh'." - exit 1 - fi -done - -# do a spot check; if we are on production warn. -if lxc remote get-default | grep -q "production"; then - echo "WARNING: You are running command against a production system!" - echo "" - - # check if there are any uncommited changes. It's dangerous to - # alter production systems when you have commits to make or changes to stash. - if git update-index --refresh | grep -q "needs update"; then - echo "ERROR: You have uncommited changes! You MUST commit or stash all changes to continue." - exit 1 - fi - - RESPONSE= - read -r -p " Are you sure you want to continue (y) ": RESPONSE - if [ "$RESPONSE" != "y" ]; then - echo "STOPPING." - exit 1 - fi - -fi - -PRIMARY_DOMAIN= -RUN_CERT_RENEWAL=true -SKIP_WWW=false -RESTORE_WWW=false -RESTORE_CERTS=false -BACKUP_CERTS=false -BACKUP_BTCPAY=false -BACKUP_CERTS=false -BACKUP_APPS=false -BACKUP_BTCPAY=false -BACKUP_BTCPAY_ARCHIVE_PATH= -RESTORE_BTCPAY=false -SKIP_BTCPAY=false -UPDATE_BTCPAY=false -REMOTE_NAME="$(lxc remote get-default)" -STOP_SERVICES=false -USER_SAYS_YES=false -RESTART_FRONT_END=true - -# grab any modifications from the command line. -for i in "$@"; do - case $i in - --restore-certs) - RESTORE_CERTS=true - shift - ;; - --restore-www) - RESTORE_WWW=true - RESTORE_CERTS=true - - shift - ;; - --restore-btcpay) - RESTORE_BTCPAY=true - shift - ;; - --backup-www) - BACKUP_CERTS=true - BACKUP_APPS=true - shift - ;; - --backup-btcpayserver) - BACKUP_BTCPAY=true - shift - ;; - --stop) - STOP_SERVICES=true - RESTART_FRONT_END=false - shift - ;; - --backup-archive-path=*) - BACKUP_BTCPAY_ARCHIVE_PATH="${i#*=}" - shift - ;; - --update-btcpay) - UPDATE_BTCPAY=true - shift - ;; - --skip-www) - SKIP_WWW=true - shift - ;; - --skip-btcpayserver) - SKIP_BTCPAY=true - shift - ;; - --no-cert-renew) - RUN_CERT_RENEWAL=false - shift - ;; - -y) - USER_SAYS_YES=true - shift - ;; - *) - echo "Unexpected option: $1" - exit 1 - ;; - esac -done - -if [ "$RESTORE_BTCPAY" = true ] && [ -z "$BACKUP_BTCPAY_ARCHIVE_PATH" ]; then - echo "ERROR: Use the '--backup-archive-path=/path/to/btcpay/archive.tar.gz' option when restoring btcpay server." - exit 1 -fi - -if [ "$RESTORE_BTCPAY" = true ] && [ ! -f "$BACKUP_BTCPAY_ARCHIVE_PATH" ]; then - echo "ERROR: The backup archive path you specified DOES NOT exist!" - exit 1 -fi - -# set up our default paths. -source ../../defaults.sh - -. ../remote_env.sh - -export REGISTRY_DOCKER_IMAGE="registry:2" -export RESTORE_WWW="$RESTORE_WWW" -export STOP_SERVICES="$STOP_SERVICES" -export BACKUP_CERTS="$BACKUP_CERTS" -export BACKUP_APPS="$BACKUP_APPS" -export RESTORE_BTCPAY="$RESTORE_BTCPAY" -export BACKUP_BTCPAY="$BACKUP_BTCPAY" -export RUN_CERT_RENEWAL="$RUN_CERT_RENEWAL" -export REMOTE_NAME="$REMOTE_NAME" -export REMOTE_PATH="$REMOTES_PATH/$REMOTE_NAME" -export USER_SAYS_YES="$USER_SAYS_YES" -export BACKUP_BTCPAY_ARCHIVE_PATH="$BACKUP_BTCPAY_ARCHIVE_PATH" -export RESTART_FRONT_END="$RESTART_FRONT_END" -export RESTORE_CERTS="$RESTORE_CERTS" - - -# todo convert this to Trezor-T -SSH_PUBKEY_PATH="$SSH_HOME/id_rsa.pub" -export SSH_PUBKEY_PATH="$SSH_PUBKEY_PATH" -if [ ! -f "$SSH_PUBKEY_PATH" ]; then - # generate a new SSH key for the base vm image. - ssh-keygen -f "$SSH_HOME/id_rsa" -t ecdsa -b 521 -N "" -fi - -# ensure our remote path is created. -mkdir -p "$REMOTE_PATH" - -REMOTE_DEFINITION="$REMOTE_PATH/remote.conf" -if [ ! -f "$REMOTE_DEFINITION" ]; then - echo "ERROR: The remote definition could not be found. You may need to re-run 'ss-remote'." - exit 1 -fi - -export REMOTE_DEFINITION="$REMOTE_DEFINITION" -source "$REMOTE_DEFINITION" -export LXD_REMOTE_PASSWORD="$LXD_REMOTE_PASSWORD" -export DEPLOYMENT_STRING="$DEPLOYMENT_STRING" - -# this is our password generation mechanism. Relying on GPG for secure password generation -function new_pass { - gpg --gen-random --armor 1 25 -} - - -function stub_site_definition { - mkdir -p "$SITE_PATH" "$PROJECT_PATH/sites" - - # create a symlink from the PROJECT_PATH/sites/DOMAIN_NAME to the ss-sites/domain name - DOMAIN_SYMLINK_PATH="$PROJECT_PATH/sites/$DOMAIN_NAME" - if [ ! -L "$DOMAIN_SYMLINK_PATH" ]; then - ln -r -s "$SITE_PATH" "$DOMAIN_SYMLINK_PATH" - fi - - if [ ! -f "$SITE_PATH/site.conf" ]; then - # check to see if the enf file exists. exist if not. - SITE_DEFINITION_PATH="$SITE_PATH/site.conf" - if [ ! -f "$SITE_DEFINITION_PATH" ]; then - - # stub out a site.conf with new passwords. - cat >"$SITE_DEFINITION_PATH" <"$PROJECT_DEFINITION_PATH" < /home/ubuntu/.ss-githead" -else - echo "INFO: Skipping www VM." -fi - -export DOMAIN_NAME="$PRIMARY_DOMAIN" -export SITE_PATH="$SITES_PATH/$DOMAIN_NAME" -if [ "$SKIP_BTCPAY" = false ]; then - ./btcpayserver/go.sh - - ssh ubuntu@"$BTCPAY_FQDN" "echo $LATEST_GIT_COMMIT > /home/ubuntu/.ss-githead" -else - echo "INFO: Skipping the btcpayserver VM." -fi \ No newline at end of file diff --git a/deploy_vm.sh b/deploy_vm.sh deleted file mode 100755 index 697a2f7..0000000 --- a/deploy_vm.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/bin/bash - -set -eu -cd "$(dirname "$0")" - -## This is a weird if clause since we need to LEFT-ALIGN the statement below. -SSH_STRING="Host ${FQDN}" -if ! grep -q "$SSH_STRING" "$SSH_HOME/config"; then - -########## BEGIN -cat >> "$SSH_HOME/config" <<-EOF - -${SSH_STRING} - HostName ${FQDN} - User ubuntu -EOF -### - -fi - -ssh-keygen -f "$SSH_HOME/known_hosts" -R "$FQDN" - -# if the machine doesn't exist, we create it. -if ! lxc list --format csv | grep -q "$LXD_VM_NAME"; then - - # create a base image if needed and instantiate a VM. - if [ -z "$MAC_ADDRESS_TO_PROVISION" ]; then - echo "ERROR: You MUST define a MAC Address for all your machines by setting WWW_SERVER_MAC_ADDRESS, BTCPAYSERVER_MAC_ADDRESS in your site definition." - echo "INFO: IMPORTANT! You MUST have DHCP Reservations for these MAC addresses. You also need records established the DNS." - exit 1 - fi - - # TODO ensure we are only GROWING the volume--never shrinking per zfs volume docs. - VM_ID= - BACKUP_DISK_SIZE_GB= - SSDATA_DISK_SIZE_GB= - DOCKER_DISK_SIZE_GB= - if [ "$VIRTUAL_MACHINE" = www ]; then - VM_ID="w" - BACKUP_DISK_SIZE_GB="$WWW_BACKUP_DISK_SIZE_GB" - SSDATA_DISK_SIZE_GB="$WWW_SSDATA_DISK_SIZE_GB" - DOCKER_DISK_SIZE_GB="$WWW_DOCKER_DISK_SIZE_GB" - fi - - if [ "$VIRTUAL_MACHINE" = btcpayserver ]; then - VM_ID="b" - BACKUP_DISK_SIZE_GB="$BTCPAYSERVER_BACKUP_DISK_SIZE_GB" - SSDATA_DISK_SIZE_GB="$BTCPAYSERVER_SSDATA_DISK_SIZE_GB" - DOCKER_DISK_SIZE_GB="$BTCPAYSERVER_DOCKER_DISK_SIZE_GB" - fi - - DOCKER_VOLUME_NAME="$PRIMARY_DOMAIN_IDENTIFIER-$VM_ID""d" - if ! lxc storage volume list ss-base | grep -q "$DOCKER_VOLUME_NAME"; then - lxc storage volume create ss-base "$DOCKER_VOLUME_NAME" --type=block - fi - - # TODO ensure we are only GROWING the volume--never shrinking - lxc storage volume set ss-base "$DOCKER_VOLUME_NAME" size="${DOCKER_DISK_SIZE_GB}GB" - - SSDATA_VOLUME_NAME="$PRIMARY_DOMAIN_IDENTIFIER-$VM_ID""s" - if ! lxc storage volume list ss-base | grep -q "$SSDATA_VOLUME_NAME"; then - lxc storage volume create ss-base "$SSDATA_VOLUME_NAME" --type=filesystem - fi - - # TODO ensure we are only GROWING the volume--never shrinking per zfs volume docs. - lxc storage volume set ss-base "$SSDATA_VOLUME_NAME" size="${SSDATA_DISK_SIZE_GB}GB" - - - BACKUP_VOLUME_NAME="$PRIMARY_DOMAIN_IDENTIFIER-$VM_ID""b" - if ! lxc storage volume list ss-base | grep -q "$BACKUP_VOLUME_NAME"; then - lxc storage volume create ss-base "$BACKUP_VOLUME_NAME" --type=filesystem - fi - - lxc storage volume set ss-base "$BACKUP_VOLUME_NAME" size="${BACKUP_DISK_SIZE_GB}GB" - - - bash -c "./stub_lxc_profile.sh --vm=$VIRTUAL_MACHINE --lxd-hostname=$LXD_VM_NAME --ss-volume-name=$SSDATA_VOLUME_NAME --backup-volume-name=$BACKUP_VOLUME_NAME" - - # now let's create a new VM to work with. - #lxc init --profile="$LXD_VM_NAME" "$BASE_IMAGE_VM_NAME" "$LXD_VM_NAME" --vm - lxc init "$DOCKER_BASE_IMAGE_NAME" "$LXD_VM_NAME" --vm --profile="$LXD_VM_NAME" - - # let's PIN the HW address for now so we don't exhaust IP - # and so we can set DNS internally. - lxc config set "$LXD_VM_NAME" "volatile.enp5s0.hwaddr=$MAC_ADDRESS_TO_PROVISION" - - # attack the docker block device. - lxc storage volume attach ss-base "$DOCKER_VOLUME_NAME" "$LXD_VM_NAME" - - # if [ "$VIRTUAL_MACHINE" = btcpayserver ]; then - # # attach any volumes - # for CHAIN in testnet mainnet; do - # for DATA in blocks chainstate; do - # MOUNT_PATH="/$CHAIN-$DATA" - # lxc config device add "$LXD_VM_NAME" "$CHAIN-$DATA" disk pool=ss-base source="$CHAIN-$DATA" path="$MOUNT_PATH" - # done - # done - # fi - - lxc start "$LXD_VM_NAME" - sleep 10 - - bash -c "./wait_for_lxc_ip.sh --lxd-name=$LXD_VM_NAME" - - # scan the remote machine and install it's identity in our SSH known_hosts file. - ssh-keyscan -H -t ecdsa "$FQDN" >> "$SSH_HOME/known_hosts" - - ssh "$FQDN" "sudo chown ubuntu:ubuntu $REMOTE_DATA_PATH" - ssh "$FQDN" "sudo chown -R ubuntu:ubuntu $REMOTE_BACKUP_PATH" - - if [ "$VIRTUAL_MACHINE" = btcpayserver ]; then - # send an updated ~/.bashrc so we have quicker access to cli tools - scp ./btcpayserver/bashrc.txt "ubuntu@$FQDN:$REMOTE_HOME/.bashrc" - ssh "$BTCPAY_FQDN" "chown ubuntu:ubuntu $REMOTE_HOME/.bashrc" - ssh "$BTCPAY_FQDN" "chmod 0664 $REMOTE_HOME/.bashrc" - fi -fi \ No newline at end of file diff --git a/domain_env.sh b/domain_env.sh index a96d1ab..8d992df 100755 --- a/domain_env.sh +++ b/domain_env.sh @@ -11,6 +11,8 @@ export NOSTR_FQDN="$NOSTR_HOSTNAME.$DOMAIN_NAME" export CLAMS_FQDN="$CLAMS_HOSTNAME.$DOMAIN_NAME" export ADMIN_ACCOUNT_USERNAME="info" export CERTIFICATE_EMAIL_ADDRESS="$ADMIN_ACCOUNT_USERNAME@$DOMAIN_NAME" + + export REMOTE_GHOST_PATH="$REMOTE_DATA_PATH/ghost" export REMOTE_NEXTCLOUD_PATH="$REMOTE_DATA_PATH/nextcloud" export REMOTE_GITEA_PATH="$REMOTE_DATA_PATH/gitea" diff --git a/project_defaults.sh b/project_defaults.sh new file mode 100644 index 0000000..512e7ae --- /dev/null +++ b/project_defaults.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +set -e + +export DEPLOY_GHOST=true +export DEPLOY_CLAMS=false +export DEPLOY_NOSTR=false +export DEPLOY_NEXTCLOUD=false +export DEPLOY_GITEA=false + + + +export SITE_LANGUAGE_CODES="en" +export LANGUAGE_CODE="en" +export NOSTR_ACCOUNT_PUBKEY= + + +# this is where the html is sourced from. +export SITE_HTML_PATH= +export BTCPAY_ADDITIONAL_HOSTNAMES= + +export GHOST_MYSQL_PASSWORD= +export GHOST_MYSQL_ROOT_PASSWORD= +export NEXTCLOUD_MYSQL_PASSWORD= +export GITEA_MYSQL_PASSWORD= +export NEXTCLOUD_MYSQL_ROOT_PASSWORD= +export GITEA_MYSQL_ROOT_PASSWORD= +export DUPLICITY_BACKUP_PASSPHRASE= + + +export BTCPAY_SERVER_CPU_COUNT="4" +export BTCPAY_SERVER_MEMORY_MB="4096" +export WWW_SERVER_CPU_COUNT="4" +export WWW_SERVER_MEMORY_MB="4096" +export DOCKER_IMAGE_CACHE_FQDN="registry-1.docker.io" + + +DEFAULT_DB_IMAGE="mariadb:10.11.2-jammy" + + + +# run the docker stack. +export GHOST_IMAGE="ghost:5.38.0" + +# TODO switch to mysql. May require intricate export work for existing sites. +# THIS MUST BE COMPLETED BEFORE v1 RELEASE +#https://forum.ghost.org/t/how-to-migrate-from-mariadb-10-to-mysql-8/29575 +export GHOST_DB_IMAGE="mysql:8.0.32" + + +export NGINX_IMAGE="nginx:1.23.3" + +# version of backup is 24.0.3 +export NEXTCLOUD_IMAGE="nextcloud:25.0.4" +export NEXTCLOUD_DB_IMAGE="$DEFAULT_DB_IMAGE" + +# TODO PIN the gitea version number. +export GITEA_IMAGE="gitea/gitea:latest" +export GITEA_DB_IMAGE="$DEFAULT_DB_IMAGE" + +export NOSTR_RELAY_IMAGE="scsibug/nostr-rs-relay" + +export WWW_SERVER_MAC_ADDRESS= +export BTCPAYSERVER_MAC_ADDRESS= + +export OTHER_SITES_LIST= +export BTCPAY_ALT_NAMES= + +export REMOTE_HOME="/home/ubuntu" +export REMOTE_DATA_PATH="$REMOTE_HOME/ss-data" +export REMOTE_DATA_PATH_LETSENCRYPT="$REMOTE_DATA_PATH/letsencrypt" +export REMOTE_BACKUP_PATH="$REMOTE_HOME/backups" +export BTCPAY_SERVER_APPPATH="$REMOTE_DATA_PATH/btcpayserver-docker" \ No newline at end of file diff --git a/stub_lxc_profile.sh b/stub_lxc_profile.sh deleted file mode 100755 index c4c1be4..0000000 --- a/stub_lxc_profile.sh +++ /dev/null @@ -1,286 +0,0 @@ -#!/bin/bash - -set -eu -cd "$(dirname "$0")" - -VIRTUAL_MACHINE=base -LXD_HOSTNAME= -SSDATA_VOLUME_NAME= -BACKUP_VOLUME_NAME= - -# grab any modifications from the command line. -for i in "$@"; do - case $i in - --lxd-hostname=*) - LXD_HOSTNAME="${i#*=}" - shift - ;; - --vm=*) - VIRTUAL_MACHINE="${i#*=}" - shift - ;; - --ss-volume-name=*) - SSDATA_VOLUME_NAME="${i#*=}" - shift - ;; - --backup-volume-name=*) - BACKUP_VOLUME_NAME="${i#*=}" - shift - ;; - *) - echo "Unexpected option: $1" - exit 1 - ;; - esac -done - -# generate the custom cloud-init file. Cloud init installs and configures sshd -SSH_AUTHORIZED_KEY=$(<"$SSH_PUBKEY_PATH") -eval "$(ssh-agent -s)" -ssh-add "$SSH_HOME/id_rsa" -export SSH_AUTHORIZED_KEY="$SSH_AUTHORIZED_KEY" - -export FILENAME="$LXD_HOSTNAME.yml" -mkdir -p "$PROJECT_PATH/cloud-init" -YAML_PATH="$PROJECT_PATH/cloud-init/$FILENAME" - -# If we are deploying the www, we attach the vm to the underlay via macvlan. -cat > "$YAML_PATH" <> "$YAML_PATH" <> "$YAML_PATH" <> "$YAML_PATH" <> "$YAML_PATH" <> "$YAML_PATH" <> "$YAML_PATH" <> "$YAML_PATH" <> "$YAML_PATH" <> "$YAML_PATH" <> "$YAML_PATH" <> "$YAML_PATH" <> "$YAML_PATH" <