# Copyright 2025-2026 Thomas Hintz # This file is part of Nassella. # Nassella 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. # Nassella 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 General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with Nassella. If not, see . TERRAFORM_ENV := production config_dir := ./config/ apps_config := $(config_dir)apps.config BUTANE := butane -d ${PWD} ifeq ($(shell command -v docker >/dev/null 2>&1 && echo yes),yes) BUTANE := docker run --rm --volume ${PWD}:/pwd --workdir /pwd -i quay.io/coreos/butane:latest -d /pwd endif IMAGE_DEPS := COMPOSE_ENVS := $(shell if [ -d app/ ]; then find app/ -type f -name '.compose-env'; fi) ALL_APPS_FILES = $(shell find all-apps/ -type f -name '*') APP_MAKEFILES := $(shell if [ -d app/ ]; then find app/ -type f -name 'Makefile'; fi) -include $(APP_MAKEFILES) # .dirstamp plus && $@ is like make magic to get this rule # to only run if the contents of all-apps changes app/.dirstamp: copy-apps.sh $(apps_config) $(ALL_APPS_FILES) rm -Rf app/ mkdir app/ cp all-apps/app.service app/ cp all-apps/restic-snapshot.service app/ ./make-top-level-docker-compose.sh $(apps_config) > app/docker-compose.yaml ./copy-apps.sh $(apps_config) && touch $@ # # compose .env files # # (compose only supports one .env file at the root by default) app/.env: $(apps_config) $(COMPOSE_ENVS) find app/ -name ".compose-env" -exec cat > app/.env {} + # Caddy / lb app/lb/lb.env: $(apps_config) app/.dirstamp make-caddyfile-env.sh mkdir -p app/lb ./make-caddyfile-env.sh $(apps_config) > $@ app/lb/Caddyfile: $(apps_config) app/.dirstamp echo "(maintenance_intercept) {" > app/lb/Caddyfile-tmp echo "@maintenanceModeActive file /maintenance/maintenance.on {" >> app/lb/Caddyfile-tmp echo " root /" >> app/lb/Caddyfile-tmp echo "}" >> app/lb/Caddyfile-tmp echo "handle @maintenanceModeActive {" >> app/lb/Caddyfile-tmp echo " respond \"We are performing a maintenance, come back later\" 503" >> app/lb/Caddyfile-tmp echo "}" >> app/lb/Caddyfile-tmp echo "}" >> app/lb/Caddyfile-tmp find app/ -name "Caddyfile" -exec cat >> app/lb/Caddyfile-tmp {} + mv app/lb/Caddyfile-tmp $@ # Backups / Restic / Backblaze restic-env: $(apps_config) make-restic-generated.sh ./make-restic-generated.sh $(apps_config) > restic-env restic-password: $(apps_config) make-restic-password.sh ./make-restic-password.sh $(apps_config) > restic-password app.tar.gz: app/.dirstamp \ app/.env \ app/lb/lb.env \ app/lb/Caddyfile tar cfz app.tar.gz app/ ignition.json: cl.yaml app/.dirstamp \ $(IMAGE_DEPS) \ app/lb/lb.env \ app/lb/Caddyfile \ restic-env \ restic-password \ restic-restore.sh \ restic-snapshot.sh \ restic-scheduled-snapshot.sh \ app/.env \ $(config_dir)ssh-keys \ app.tar.gz cat cl.yaml | $(BUTANE) > ignition.json generated.tfvars: $(apps_config) make-generated.sh ./make-generated.sh $(apps_config) > generated.tfvars plan: ignition.json $(config_dir)$(TERRAFORM_ENV).tfvars generated.tfvars terraform init bash -c "terraform plan -var-file=<(cat $(config_dir)$(TERRAFORM_ENV).tfvars generated.tfvars)" .PHONY: announce-start announce-start: echo "NASSELLA_CONFIG: start" # run this first to generate the all/ dir # then we can 'include' all the Makefiles in all/ .PHONY: preapply preapply: app/.dirstamp echo "app generated" apply: announce-start restic-init ignition.json $(config_dir)$(TERRAFORM_ENV).tfvars generated.tfvars echo "NASSELLA_CONFIG: end" terraform init bash -c "terraform apply -auto-approve -input=false -var-file=<(cat $(config_dir)$(TERRAFORM_ENV).tfvars generated.tfvars)" destroy: ignition.json $(config_dir)$(TERRAFORM_ENV).tfvars generated.tfvars terraform init bash -c "terraform destroy -auto-approve -input=false -var-file=<(cat $(config_dir)$(TERRAFORM_ENV).tfvars generated.tfvars)" .PHONY: restic-init restic-init: $(apps_config) restic-password ./init-restic.sh $(apps_config) ## just an easy way to see snapshots that have been taken .PHONY: restic-snapshots restic-snapshots: $(apps_config) restic-password ./restic-snapshots.sh $(apps_config) .PHONY: archive archive: echo "(" > all-apps/root-napp.scm find all-apps/ -name "napp.scm" -exec cat >> all-apps/root-napp.scm {} + echo ")" >> all-apps/root-napp.scm tar -cf nassella-latest.tar all-apps cl.yaml init-restic.sh main.tf make-caddyfile-env.sh make-top-level-docker-compose.sh Makefile \ make-generated.sh make-restic-generated.sh make-restic-password.sh restic-snapshots.sh copy-apps.sh restic-restore.sh restic-snapshot.sh \ restic-scheduled-snapshot.sh \ .terraform.lock.hcl cp nassella-latest.tar src/ ## to help me remember the command to run to test the config locally testlocalhost: curl -k --resolve localhost:443:146.190.12.129 https://localhost flatcarbuild: ignition.json cp --reflink=auto flatcar/flatcar_production_qemu_image.img.fresh flatcar/flatcar_production_qemu_image.img flatcarrun: ./flatcar/flatcar_production_qemu.sh -i ignition.json