diff --git a/Makefile b/Makefile
index 882573a..f668b9c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,2 @@
WEBMIN_FW_TCP_INCOMING = 22 80 443 3000 12321
-
-RUBY_VER=3.1
-include $(FAB_PATH)/common/mk/turnkey/rails-pgsql.mk
-include $(FAB_PATH)/common/mk/turnkey/nodejs.mk
include $(FAB_PATH)/common/mk/turnkey.mk
diff --git a/conf.d/10ruby b/conf.d/10ruby
deleted file mode 100755
index 704d241..0000000
--- a/conf.d/10ruby
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash -ex
-
-source /usr/local/src/canvas.conf
-
-GEMOPTS='--no-document'
-
-# install gems
-[ "$FAB_HTTP_PROXY" ] && export http_proxy=$FAB_HTTP_PROXY
-
-gem install $GEMOPTS psych
-gem install $GEMOPTS activesupport
-gem update $GEMOPTS strscan
-unset http_proxy
-
diff --git a/conf.d/30rails b/conf.d/30rails
deleted file mode 100755
index 6dae34d..0000000
--- a/conf.d/30rails
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash -ex
-
-source /usr/local/src/canvas.conf
-
-# get db_pass set by common/rails and update canvas.conf
-DB_PASS=$(grep password: $WEBROOT/config/database.yml | head -n 1 | awk '{print $2}')
-sed -i "s|DB_PASS=.*|DB_PASS=$DB_PASS|" /usr/local/src/canvas.conf
-
-# remove common/rails webroot
-rm -rf $WEBROOT
-
diff --git a/conf.d/40database b/conf.d/40database
deleted file mode 100755
index 051ead5..0000000
--- a/conf.d/40database
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash -ex
-
-source /usr/local/src/canvas.conf
-
-service postgresql start
-
-su postgres -c "createdb --owner $DB_USER -EUTF8 $DB_QUEUE"
-su postgres -c "psql postgres" <<< "alter user $DB_USER with encrypted password '$DB_PASS';"
diff --git a/conf.d/50canvas-clone b/conf.d/50canvas-clone
deleted file mode 100755
index aa36609..0000000
--- a/conf.d/50canvas-clone
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/bash -ex
-
-source /usr/local/src/canvas.conf
-
-# download and set branch to version
-URL="https://github.com/instructure/canvas-lms.git"
-
-[ "$FAB_HTTP_PROXY" ] && export HTTP_PROXY=$FAB_HTTP_PROXY
-git clone $URL $WEBROOT --depth=1 -b prod
-unset HTTP_PROXY
-
-cd $WEBROOT
-
-# tweak footer
-CONF=$WEBROOT/app/views/layouts/application.html.erb
-sed -i "s||
\n |" $CONF
diff --git a/conf.d/52canvas-configs b/conf.d/52canvas-configs
deleted file mode 100755
index 47f7cfb..0000000
--- a/conf.d/52canvas-configs
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/bin/bash -ex
-
-source /usr/local/src/canvas.conf
-
-# setup database config
-cat >$WEBROOT/config/database.yml<$WEBROOT/config/outgoing_mail.yml<$WEBROOT/config/domain.yml<$WEBROOT/config/cache_store.yml<$WEBROOT/config/redis.yml<$WEBROOT/config/delayed_jobs.yml<$WEBROOT/config/vault_contents.yml<$WEBROOT/config/security.yml<$WEBROOT/config/dynamic_settings.yml< config/GEM_HOME
-export GEM_HOME=$(cat config/GEM_HOME)
-
-yarn config set strict-ssl false
-npm install -g yarn@1.22.19 wsrun
-mkdir -p $YARN_CACHE
-yarn install --network-timeout 1000000 --scripts-prepend-node-path --cache-folder $YARN_CACHE
-
-# COMPILE_ASSETS_BRANC_CONFIGS variable:
-# https://github.com/instructure/canvas-lms/issues/2023
-
-# fix for webpack failure
-# https://stackoverflow.com/questions/69692842/error-message-error0308010cdigital-envelope-routinesunsupported
-sed -i 's/5120/5120 --openssl-legacy-provider/g' package.json
-
-COMPILE_ASSETS_BRAND_CONFIGS=0 bundle exec rake canvas:compile_assets
-chown -R www-data:www-data $WEBROOT/public/dist/brandable_css
-
-# apply another patch; this time to the init script
-_patch=/usr/local/src/canvas_init.patch
-git apply $_patch
-rm -rf $_patch
-
-# https://github.com/instructure/canvas-lms/issues/2034
-# mv db/migrate/20210812210129_add_singleton_column.rb db/migrate/20111111214311_add_singleton_column.rb
-# https://github.com/instructure/canvas-lms/issues/2035
-# mv db/migrate/20210823222355_change_immersive_reader_allowed_on_to_on.rb .
-# weird zeitwerk path issue fix
-sed -i 's|\(lib/ssl_common\)|./\1|' app/models/report_snapshot.rb
-bundle exec rake db:initial_setup
-# mv 20210823222355_change_immersive_reader_allowed_on_to_on.rb db/migrate/
-bundle exec rake db:migrate
-
-# resolve (errant) 'failed to allocate memory' issue - closes
-# https://github.com/turnkeylinux/tracker/issues/1965
-bundle exec rake switchman_inst_jobs:install:migrations
-
-mkdir -p log tmp/pids public/assets
-
-# stop services
-service postgresql stop
-service redis-server stop
-
-unset http_proxy
-
-# clean out installation log
-rm -f $WEBROOT/log/*
-rm -rf $YARN_CACHE
diff --git a/conf.d/70initscript b/conf.d/70initscript
deleted file mode 100755
index d48a3be..0000000
--- a/conf.d/70initscript
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash -ex
-
-source /usr/local/src/canvas.conf
-
-# setup automated jobs
-ln -s $WEBROOT/script/canvas_init /etc/init.d/canvas_init
-
-# changes applied with patch in overlays/usr/local/src/canvas_init.patch
-# during conf.d/55canvas-install
-# sed -i '/exec su/ s#$# -s /bin/bash#' $WEBROOT/script/canvas_init
-# sed -i "s|exec script\/delayed_job \$@|bundle exec script\/delayed_job \$\@|" $WEBROOT/script/canvas_init
-
-update-rc.d canvas_init defaults
diff --git a/conf.d/90finish b/conf.d/90finish
deleted file mode 100755
index f91adeb..0000000
--- a/conf.d/90finish
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/bash -ex
-
-WEBROOT=/var/www/canvas
-
-BUNDLE_PATH="$WEBROOT/vendor/bundle"
-GEM_PATH="$(cat "$WEBROOT/config/GEM_HOME")"
-
-if [[ -z "$BUNDLE_PATH" ]] || [[ ! -d "$BUNDLE_PATH" ]]; then
- echo "Fatal: BUNDLE_PATH ($BUNDLE_PATH) does not exist"
-fi
-if [[ -z "$GEM_PATH" ]] || [[ ! -d "$GEM_PATH" ]]; then
- echo "Fatal: GEM_PATH ($GEM_PATH) does not exist"
-fi
-
-APACHE_CONF=/etc/apache2/sites-available/canvas.conf
-sed -i "/BUNDLE_PATH/ s|__BUNDLE_PATH__|$BUNDLE_PATH|" "$APACHE_CONF"
-sed -i "/GEM_PATH/ s|__GEM_PATH__|$GEM_PATH|" "$APACHE_CONF"
-
-# create convenience symlink for logs
-rm -rf /var/log/canvas
-ln -s $WEBROOT/log /var/log/canvas
-
-chown -R www-data:www-data /var/www/canvas/{config,log}
-
-# fix for github.com/phusion/passenger/wiki/Debugging-application-startup-problems
-echo "PassengerStartTimeout 300" >> /etc/apache2/mods-available/passenger.conf
-
-# part of fix for https://github.com/phusion/passenger/issues/2397
-echo "PassengerInstanceRegistryDir /run/passenger-instreg" >> /etc/apache2/mods-available/passenger.conf
-# see also /etc/tmpfiles.d/passenger.conf in overlay
-
-chmod 400 $WEBROOT/config/cache_store.yml
-
-rm -f /usr/local/src/canvas.conf
diff --git a/conf.d/main b/conf.d/main
new file mode 100755
index 0000000..660b20d
--- /dev/null
+++ b/conf.d/main
@@ -0,0 +1,188 @@
+#!/bin/bash -ex
+
+export VERSION_CANVAS=prod
+
+export SRC=/usr/local/src
+export WEBROOT=/var/www/canvas
+export APPROOT=/usr/src/app
+
+export ADMIN_PASS=turnkey1
+export ADMIN_MAIL=admin@example.com
+export DOMAIN=www.example.com
+
+export DB_USER=canvas
+export DB_NAME=canvas_production
+export DB_PASS=turnkey1
+export DB_QUEUE=canvas_queue_production
+
+download() {
+ [ "$FAB_HTTP_PROXY" ] && PROXY="--proxy $FAB_HTTP_PROXY"
+ cd $2; curl -L -f -O $PROXY $1; cd -
+}
+
+# download and set branch to version
+URL="https://github.com/instructure/canvas-lms.git"
+
+[ "$FAB_HTTP_PROXY" ] && export HTTP_PROXY=$FAB_HTTP_PROXY
+git clone "$URL" "$WEBROOT" --depth=1 -b "$VERSION_CANVAS"
+unset HTTP_PROXY
+
+cd $WEBROOT
+
+# setup database config
+cat >$WEBROOT/config/database.yml<$WEBROOT/config/outgoing_mail.yml<$WEBROOT/config/domain.yml<$WEBROOT/config/cache_store.yml<$WEBROOT/config/redis.yml<$WEBROOT/config/delayed_jobs.yml<$WEBROOT/config/vault_contents.yml<$WEBROOT/config/security.yml<$WEBROOT/config/dynamic_settings.yml<| \
+ \
+| \
+" "$WEBROOT/app/views/layouts/application.html.erb"
+
+# tweak Dockerfile
+sed -i 's|\(rm -rf node_modules\)|\1 /home/docker/.cache /home/docker/.gem/3.3/cache /usr/src/app/public/dist/webpack-dev|' Dockerfile.production
+
+# tweak confconsole so it doesn't show podman NIC by default
+sed -i '/^#default_nic/s/^#//' /etc/confconsole/confconsole.conf
+
+### all of the following would be similar for all containerized appliances
+
+# clean up build fs
+fs_cleanup() {
+ set +e
+ mount -l -t fuse.fuse-overlayfs | cut -d " " -f3 | xargs -rL1 fusermount -u
+ umount -vRf /sys
+ rm /dev/fuse
+}
+
+# umount everything if build fails or deck won't umount
+trap fs_cleanup INT TERM EXIT
+
+# podman requires sysfs & cgroups
+# fuse-overlayfs requires fusectl & fuse device
+# native overlayfs refuses to work on top of deck overlayfs
+# vfs works; it is heavier and slower and incompatible with overlay but less fragile
+mount -t sysfs sysfs /sys -o ro,nosuid,nodev,noexec,relatime
+mkdir -p /sys/fs/{cgroup,fuse/connections}
+mount -t cgroup2 cgroup2 /sys/fs/cgroup -o rw,nosuid,nodev,noexec,relatime
+mount -t fusectl fusectl /sys/fs/fuse/connections -o rw,nosuid,nodev,noexec,relatime
+mknod /dev/fuse -m 0666 c 10 229
+
+# get deps
+RUBY_VERSION="$(grep -Po '^ARG RUBY[= ]\K.+$' Dockerfile.production)"
+RUBY_IMAGE="$(grep -Po '^FROM \K[^:]*' Dockerfile.production)"
+PG_VERSION="$(grep -Po 'POSTGRES_CLIENT[= ]\K[[:digit:]]+' Dockerfile.production)"
+
+BUILD_DEPS=( "$RUBY_IMAGE:$RUBY_VERSION" )
+RUN_DEPS=( "postgres:$PG_VERSION-alpine" nginx:alpine redis:alpine instructure/canvas-rce-api )
+DEPS=( "${BUILD_DEPS[@]}" "${RUN_DEPS[@]}" )
+
+export RUBY_VERSION RUBY_IMAGE PG_VERSION BUILD_DEPS RUN_DEPS DEPS
+for i in ${DEPS[@]}; do podman pull "docker.io/$i"; done
+
+# build image
+# retry a few times because of possible network issues ruining the build
+for i in $(seq 1 3); do
+ podman build --isolation chroot -t canvas -f Dockerfile.production .
+done
+
+for i in canvas "${RUN_DEPS[@]}"; do
+ NAME="$(basename "$i" | cut -d':' -f1)"
+ podman save --format oci-dir -o "$SRC/images/$NAME" "$i"
+done
+
+podman system reset -f
diff --git a/overlay/etc/apache2/sites-available/canvas.conf b/overlay/etc/apache2/sites-available/canvas.conf
deleted file mode 100644
index b40d0b5..0000000
--- a/overlay/etc/apache2/sites-available/canvas.conf
+++ /dev/null
@@ -1,38 +0,0 @@
-ServerName localhost
-
-
- UseCanonicalName Off
- ServerAdmin webmaster@localhost
- DocumentRoot /var/www/canvas/public
- RewriteEngine On
- RewriteCond %{HTTP:X-Forwarded-Proto} !=https
- RewriteCond %{REQUEST_URI} !^/health_checkk
- RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L]
-
-
-
- SSLEngine on
- ServerAdmin youremail@example.com
- DocumentRoot /var/www/canvas/public
- SetEnv RAILS_ENV production
- SetEnv BUNDLE_PATH "__BUNDLE_PATH__"
- SetEnv GEM_PATH "__GEM_PATH__"
-
-
-
- Options All
- AllowOverride All
- Require all granted
-
-
-
- SSLEngine on
- PassengerAppRoot /var/www/canvas-rce-api
- PassengerAppType node
- PassengerStartupFile app.js
-
-
-
- Options -MultiViews
- Require all granted
-
diff --git a/overlay/etc/logrotate.d/canvas b/overlay/etc/logrotate.d/canvas
deleted file mode 100644
index 9701f6c..0000000
--- a/overlay/etc/logrotate.d/canvas
+++ /dev/null
@@ -1,12 +0,0 @@
-# Canvas logrotate settings
-# based on: http://stackoverflow.com/a/4883967
-
-/var/www/canvas/log/*.log {
- daily
- missingok
- rotate 90
- compress
- delaycompress
- notifempty
- copytruncate
-}
diff --git a/overlay/etc/nginx/conf.d/canvas.conf b/overlay/etc/nginx/conf.d/canvas.conf
new file mode 100644
index 0000000..49dd67d
--- /dev/null
+++ b/overlay/etc/nginx/conf.d/canvas.conf
@@ -0,0 +1,44 @@
+server {
+ listen 80 default_server;
+ server_name _;
+
+ location / {
+ return 301 https://$http_host$request_uri;
+ }
+}
+
+server {
+ listen 443 ssl default_server;
+ server_name _;
+ http2 on;
+
+ ssl_certificate /etc/ssl/private/cert.pem;
+ ssl_certificate_key /etc/ssl/private/cert.key;
+ ssl_dhparam /etc/ssl/private/dhparams.pem;
+
+ proxy_set_header X-Forwarded-Host $http_host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ location / {
+ proxy_pass http://127.0.0.1:8080;
+ }
+}
+
+server {
+ listen 3000 ssl default_server;
+ server_name _;
+ http2 on;
+
+ ssl_certificate /etc/ssl/private/cert.pem;
+ ssl_certificate_key /etc/ssl/private/cert.key;
+ ssl_dhparam /etc/ssl/private/dhparams.pem;
+
+ proxy_set_header X-Forwarded-Host $http_host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ location / {
+ proxy_pass http://127.0.0.1:8081;
+ }
+}
diff --git a/overlay/etc/tmpfiles.d/passenger.conf b/overlay/etc/tmpfiles.d/passenger.conf
deleted file mode 100644
index d8f4e76..0000000
--- a/overlay/etc/tmpfiles.d/passenger.conf
+++ /dev/null
@@ -1 +0,0 @@
-d /run/passenger-instreg 0755 root root -
diff --git a/overlay/usr/lib/inithooks/bin/canvas.py b/overlay/usr/lib/inithooks/bin/canvas.py
index 6d08347..e1e9c2b 100755
--- a/overlay/usr/lib/inithooks/bin/canvas.py
+++ b/overlay/usr/lib/inithooks/bin/canvas.py
@@ -13,13 +13,11 @@
import hashlib
import random
import string
-import psycopg2
import subprocess
from libinithooks import inithooks_cache
from libinithooks.dialog_wrapper import Dialog
-
def usage(s=None):
if s:
print("Error:", s, file=sys.stderr, **kwargs)
@@ -27,10 +25,8 @@ def usage(s=None):
print(__doc__, file=sys.stderr)
sys.exit(1)
-
DEFAULT_DOMAIN = "www.example.com"
-
def main():
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], "h",
@@ -82,53 +78,40 @@ def main():
inithooks_cache.write('APP_DOMAIN', domain)
- salt = "".join(random.choice(string.ascii_letters) for line in range(20))
+ salt = "".join(random.choice(string.ascii_letters) for _ in range(20))
hash = password + salt
- for i in range(20):
+
+ for _ in range(20):
hash = hashlib.sha512(hash.encode('utf-8')).hexdigest()
- access_token = "".join(random.choice(string.ascii_letters)
- for line in range(20))
-
- conn = psycopg2.connect("dbname=canvas_production user=root")
- c = conn.cursor()
- c.execute('UPDATE users SET name=%s, sortable_name=%s WHERE id=1;',
- (email, email))
- c.execute('UPDATE pseudonyms SET unique_id=%s, crypted_password=%s, password_salt=%s, single_access_token=%s WHERE user_id=1;',
- (email, hash, salt, access_token))
- c.execute('UPDATE communication_channels SET path=%s WHERE id=1;',
- (email, ))
- conn.commit()
- c.close()
- conn.close()
-
- config = "/var/www/canvas/config/outgoing_mail.yml"
- subprocess.run(["sed", "-ri",
- 's|domain:.*|domain: "%s"|' % domain,
- config])
- subprocess.run(["sed", "-ri",
- 's|outgoing_address:.*|outgoing_address: "%s"|' % email,
- config])
-
- config = "/var/www/canvas/config/dynamic_settings.yml"
- subprocess.run(["sed", "-ri",
- 's|app-host:.*|app-host: "%s:3000"|' % domain,
- config])
-
- config = "/var/www/canvas/config/domain.yml"
- subprocess.run(["sed", "-ri",
- 's|domain:.*|domain: "%s"|' % domain,
- config])
-
- config = "/var/www/canvas/config/initializers/outgoing_mail.rb"
- subprocess.run(["sed", "-ri",
- 's|:domain => .*|:domain => "%s",|' % domain,
- config])
+ access_token = "".join(random.choice(string.ascii_letters) for _ in range(20))
- print("Restarting services; please wait...")
- for service in ['canvas_init', 'apache2']:
- subprocess.run(['systemctl', 'restart', service])
+ stmts = [
+ "UPDATE communication_channels SET path='%s' WHERE id=1;" % (email),
+ "UPDATE users SET name='%s', sortable_name='%s' WHERE id=1;" % (email, email),
+ "UPDATE pseudonyms SET unique_id='%s', crypted_password='%s', password_salt='%s', single_access_token='%s' WHERE user_id=1;" % (email, hash, salt, access_token),
+ ]
+
+ for stmt in stmts:
+ subprocess.run(["podman", "exec", "db", "psql", "-U", "canvas", "canvas_production", "-c", stmt])
+ root = "/var/www/canvas/config/"
+
+ config = root + "outgoing_mail.yml"
+ subprocess.run(["sed", "-ri", 's|domain:.*|domain: "%s"|' % domain, config])
+ subprocess.run(["sed", "-ri", 's|outgoing_address:.*|outgoing_address: "%s"|' % email, config])
+
+ config = root + "dynamic_settings.yml"
+ subprocess.run(["sed", "-ri", 's|app-host:.*|app-host: "%s:3000"|' % domain, config])
+
+ config = root + "domain.yml"
+ subprocess.run(["sed", "-ri", 's|domain:.*|domain: "%s"|' % domain, config])
+
+ config = root + "initializers/outgoing_mail.rb"
+ subprocess.run(["sed", "-ri", 's|:domain => .*|:domain => "%s",|' % domain, config])
+
+ print("Restarting services; please wait...")
+ subprocess.run(['podman', 'restart', 'canvas'])
if __name__ == "__main__":
main()
diff --git a/overlay/usr/lib/inithooks/firstboot.d/19canvas-pod b/overlay/usr/lib/inithooks/firstboot.d/19canvas-pod
new file mode 100755
index 0000000..5b75cf1
--- /dev/null
+++ b/overlay/usr/lib/inithooks/firstboot.d/19canvas-pod
@@ -0,0 +1,128 @@
+#!/bin/bash -ex
+# initialize Canvas pod
+
+. /etc/default/inithooks
+
+[ -e "$INITHOOKS_CONF" ] && . "$INITHOOKS_CONF"
+
+SRC='/usr/local/src'
+WWW='/var/www/canvas'
+
+echo 'Loading Podman images...'
+
+# Approximate peak RAM usage on live:
+# - tar with or without compression: 2x
+# .tar.X (disk) -> .tar (RAM)
+# .tar (disk) -> .tar (RAM)
+# .tar (RAM) -> dir (RAM)
+# - dir: 1x
+# dir (disk) -> dir (RAM)
+# this is due to Podman keeping a copy of the tarball when loading.
+
+if mount | grep -q 'on / .*live'; then
+ # grow tmpfs
+ mount -o remount,size=90% /run/live/overlay
+
+ MAX="$(du -sm "$SRC/images" | sort -rh | head -1 | cut -f1)"
+ FREE="$(free -m | head -2 | tail -1 | awk '{print $7;}')"
+
+ echo "Running live -- checking memory usage."
+ echo "Max memory used for images will be ${MAX}M, ${FREE}M is currently free."
+
+ if [[ "$MAX" -ge "$FREE" ]]; then
+ echo "max ${MAX}M >= free ${FREE}M!"
+ echo "Install to disk or add more RAM."
+ echo "Cannot run live on this system, exiting."
+ exit 1
+ else
+ echo 'This is fine.'
+ fi
+fi
+
+# load and clean up images
+for i in "$SRC/images"/*; do
+ podman load -qi "${i}"
+
+ # restore old tag for sane updates later
+ TAG="$(basename "$i")"
+ ORIG_TAG="$(jq -r '.manifests | .[] | .annotations | .[]' "${i}/index.json")"
+ podman tag "$TAG" "$ORIG_TAG" # restores original registry tag
+ podman rmi "localhost$i:latest" # removes just the one local tag
+ rm -r "${i}"
+done
+
+echo 'Images loaded:'
+podman images
+
+# set up pod and db
+echo 'Setting up pod...'
+
+DB_CFG="$WWW/config/database.yml"
+
+DB_USER="$(grep -Po 'username: \K.*$' "$DB_CFG")"
+DB_NAME="$(grep -Po 'database: \K.*$' "$DB_CFG")"
+DB_PASS="$(grep -Po 'password: \K.*$' "$DB_CFG")"
+
+PG_VOLUME='pgdata:/var/lib/postgresql/data'
+PG_MAJOR="$(podman image inspect canvas | grep -m1 -Po 'POSTGRES_CLIENT=\K\d+')"
+PG_IMAGE="postgres:$PG_MAJOR-alpine"
+
+podman volume create pgdata
+podman pod create --name canvas-pod -p 80:80 -p 443:443 -p 3000:3000
+
+pod() {
+ op="$1"
+ shift
+
+ case "$op" in
+ run)
+ set -- --rm "$@"
+ ;;
+ create)
+ set -- --replace --restart always "$@"
+ ;;
+ esac
+
+ set -- "$op" --pod canvas-pod "$@"
+ podman "$@"
+}
+
+# create db
+echo 'Setting up databases...'
+
+pod run -d \
+ --name db \
+ -v "$PG_VOLUME" \
+ -e "POSTGRES_USER=$DB_USER" \
+ -e "POSTGRES_DB=$DB_NAME" \
+ -e "POSTGRES_PASSWORD=$DB_PASS" \
+ "$PG_IMAGE"
+
+CFG_VOLUME="$WWW/config:/usr/src/app/config:U"
+
+# initialize db
+pod run \
+ -e 'CANVAS_LMS_ADMIN_EMAIL=admin@example.com' \
+ -e 'CANVAS_LMS_ADMIN_PASSWORD=turnkey1' \
+ -e 'CANVAS_LMS_ACCOUNT_NAME=TurnKey Canvas' \
+ -e 'CANVAS_LMS_STATS_COLLECTION=opt-out' \
+ -v "$CFG_VOLUME" \
+ canvas bundle exec rake db:initial_setup
+
+# recreate db with no envvars
+pod create --name db -v "$PG_VOLUME" "$PG_IMAGE"
+
+# create redis
+pod create --name redis redis:alpine
+
+# create nginx reverse proxy
+echo 'Setting up nginx...'
+
+NGX_VOLUME="/etc/nginx/conf.d:/etc/nginx/conf.d:ro"
+TLS_VOLUME="/etc/ssl/private:/etc/ssl/private:ro"
+
+pod create --name nginx -v "$NGX_VOLUME" -v "$TLS_VOLUME" nginx:alpine
+
+podman pod start canvas-pod
+
+# canvas and canvas-rce-api are created later in 20regen-canvas-secrets with fresh secrets
diff --git a/overlay/usr/lib/inithooks/firstboot.d/20regen-canvas-secrets b/overlay/usr/lib/inithooks/firstboot.d/20regen-canvas-secrets
index 2af0036..6d1006a 100755
--- a/overlay/usr/lib/inithooks/firstboot.d/20regen-canvas-secrets
+++ b/overlay/usr/lib/inithooks/firstboot.d/20regen-canvas-secrets
@@ -1,27 +1,58 @@
-#!/bin/bash -e
+#!/bin/bash -ex
# regenerate Canvas secrets
. /etc/default/inithooks
-[ -e $INITHOOKS_CONF ] && . $INITHOOKS_CONF
+[ -e "$INITHOOKS_CONF" ] && . "$INITHOOKS_CONF"
-# Canvas Rich Content Editor API keys
-ENV_FILE=/var/www/canvas-rce-api/.env
-VAULT_CONTENTS=/var/www/canvas/config/vault_contents.yml
-SECURITY=/var/www/canvas/config/security.yml
+WEBROOT='/var/www/canvas'
-SECRET=$(mcookie)
-KEY=$(mcookie)
-EKEY=$(mcookie)
+# security.yml
+SECURITY="$WEBROOT/config/security.yml"
-sed -i "s|ECOSYSTEM_KEY=.*|ECOSYSTEM_KEY=\"$SECRET\"|" $ENV_FILE
-sed -i "s|ECOSYSTEM_SECRET=.*|ECOSYSTEM_SECRET=\"$KEY\"|" $ENV_FILE
-sed -i "s|CIPHER_PASSWORD=.*|CIPHER_PASSWORD=\"NOT_USED\"|" $ENV_FILE
-sed -i "s|signing_secret: .*|signing_secret: \"$KEY\"|" $VAULT_CONTENTS
-sed -i "s|encryption_secret: .*|encryption_secret: \"$SECRET\"|" $VAULT_CONTENTS
-sed -i "s|encryption_key: .*|encryption_key: \"$EKEY\"|" $SECURITY
+EKEY="$(mcookie)"
+sed -i "s|\(encryption_key\): .*|\1: \"$EKEY\"|" $SECURITY
-su -s /bin/bash -l www-data -c "cd /var/www/canvas && RAILS_ENV=production BUNDLE_PATH='vendor/bundle' bundle exec rake db:reset_encryption_key_hash"
+# vault_contents.yml
+VAULT_CONTENTS="$WEBROOT/config/vault_contents.yml"
-# Perhaps should restart apache (mod_passenger) here? Canvas is so slow to
-# start though, will just do it in interactive hook (rather than twice).
+ECOSYSTEM_KEY="$(mcookie)"
+ECOSYSTEM_SECRET="$(mcookie)"
+
+sed -i "s|\(signing_secret\): .*|\1: \"$ECOSYSTEM_KEY\"|" "$VAULT_CONTENTS"
+sed -i "s|\(encryption_secret\): .*|\1: \"$ECOSYSTEM_SECRET\"|" "$VAULT_CONTENTS"
+
+# database.yml
+DBCONFIG="$WEBROOT/config/database.yml"
+
+DB_USER="$(grep -Po 'username: \K.*$' "$DBCONFIG")"
+DB_NAME="$(grep -Po 'database: \K.*$' "$DBCONFIG")"
+DB_PASS="$(mcookie)"
+
+# db password
+podman exec db psql -U "$DB_USER" "$DB_NAME" -c "ALTER USER $DB_USER WITH PASSWORD '$DB_PASS';"
+sed -i "s|\(password\): .*$|\1: $DB_PASS|" "$DBCONFIG"
+
+# canvas-rce-api
+export ECOSYSTEM_KEY ECOSYSTEM_SECRET
+
+# the STATSD_ envvars are useless but it won't run without them
+podman create \
+ --replace \
+ --pod canvas-pod \
+ --restart always \
+ --name canvas-rce-api \
+ -e 'CG_HTTP_PORT=8081' \
+ -e 'CG_HTTPS_PORT=8081' \
+ -e ECOSYSTEM_KEY \
+ -e ECOSYSTEM_SECRET \
+ -e STATSD_HOST=127.0.0.1 \
+ -e STATSD_PORT=8125 \
+ instructure/canvas-rce-api
+
+WWW='/var/www/canvas'
+CFG_VOLUME="$WWW/config:/usr/src/app/config:U"
+
+podman run --rm --pod canvas-pod -v "$CFG_VOLUME" canvas bundle exec rake db:reset_encryption_key_hash
+podman create --pod canvas-pod --restart always --replace --name canvas -v "$CFG_VOLUME" -e 'CG_HTTP_PORT=8080' -e 'CG_HTTPS_PORT=8080' canvas
+podman pod start canvas-pod
diff --git a/overlay/usr/lib/inithooks/firstboot.d/40canvas b/overlay/usr/lib/inithooks/firstboot.d/40canvas
index 5ea91bf..ba4d7fb 100755
--- a/overlay/usr/lib/inithooks/firstboot.d/40canvas
+++ b/overlay/usr/lib/inithooks/firstboot.d/40canvas
@@ -1,8 +1,8 @@
#!/bin/bash -e
-# set canvas admin password, email and domain to serve
+# set Canvas admin password, email and domain to serve
. /etc/default/inithooks
-[ -e $INITHOOKS_CONF ] && . $INITHOOKS_CONF
+[ -e "$INITHOOKS_CONF" ] && . "$INITHOOKS_CONF"
-$INITHOOKS_PATH/bin/canvas.py --pass="$APP_PASS" --email="$APP_EMAIL" --domain="$APP_DOMAIN"
+"$INITHOOKS_PATH/bin/canvas.py" --pass="$APP_PASS" --email="$APP_EMAIL" --domain="$APP_DOMAIN"
diff --git a/overlay/usr/local/src/canvas.conf b/overlay/usr/local/src/canvas.conf
deleted file mode 100644
index 0cadb28..0000000
--- a/overlay/usr/local/src/canvas.conf
+++ /dev/null
@@ -1,21 +0,0 @@
-# central configuration and functions used by conf.d scripts
-
-export VERSION_CANVAS=prod
-
-export SRC=/usr/local/src
-export WEBROOT=/var/www/canvas
-
-export ADMIN_PASS=turnkey1
-export ADMIN_MAIL=admin@example.com
-export DOMAIN=www.example.com
-
-export DB_USER=canvas
-export DB_PASS= # will be updated by conf.d/30rails
-export DB_NAME=canvas_production
-export DB_QUEUE=canvas_queue_production
-
-download() {
- [ "$FAB_HTTP_PROXY" ] && PROXY="--proxy $FAB_HTTP_PROXY"
- cd $2; curl -L -f -O $PROXY $1; cd -
-}
-
diff --git a/overlay/usr/local/src/canvas_init.patch b/overlay/usr/local/src/canvas_init.patch
deleted file mode 100644
index 58d380e..0000000
--- a/overlay/usr/local/src/canvas_init.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff --git a/script/canvas_init b/script/canvas_init
-index 79d2b0ea..5fb7d2b1 100755
---- a/script/canvas_init
-+++ b/script/canvas_init
-@@ -13,7 +13,7 @@ set -e
-
- # drop privs if necessary
- if [ "$(id -u)" == "0" ]; then
-- exec su $(stat -c %U $(dirname $(readlink -f $0))/../config/environment.rb) -c "/bin/bash $0 $@"
-+ exec su $(stat -c %U $(dirname $(readlink -f $0))/../config/environment.rb) -c "/bin/bash $0 $@" -s /bin/bash
- exit -1;
- fi
-
-@@ -26,6 +26,7 @@ if [ -e "config/GEM_HOME" ]; then
- fi
- #export GEM_HOME=/path/to/gem/home
- export RAILS_ENV=production
-+export BUNDLE_PATH="vendor/bundle"
-
- # run delayed jobs
--exec script/delayed_job $@
-+bundle exec script/delayed_job $@
diff --git a/overlay/usr/local/src/images/.keep b/overlay/usr/local/src/images/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/plan/main b/plan/main
index cd178dc..8ed284d 100644
--- a/plan/main
+++ b/plan/main
@@ -1,15 +1,6 @@
#include
-#include
-/* canvas related (not in rails plan) */
-libyaml-dev
-libpq-dev
-libxmlsec1
-libxmlsec1-dev
-zlib1g-dev
-imagemagick
-redis-server
-libsqlite3-dev
-libmariadb-dev
-python3-psycopg2
-libidn11-dev /* for ruby-idn */
+jq
+podman
+catatonit
+fuse-overlayfs