Nicolas Massé 4 weeks ago
parent
commit
0c30bfb786
  1. 4
      Makefile
  2. 168
      Makefile.common
  3. 3
      base/Makefile
  4. 20
      base/rpm-ostree-install-qemu-guest-agent.service
  5. 0
      base/tmpfiles.d/base.conf
  6. 4
      base/var-lib-virtiofs-data.mount
  7. 41
      local.bu.template
  8. 1
      nextcloud/Makefile
  9. 11
      nextcloud/fcos.bu
  10. 8
      nginx/fcos.bu
  11. 3
      postgresql/Makefile
  12. 9
      postgresql/fcos.bu
  13. 8
      qemu-user-static/Makefile
  14. 9
      qemu-user-static/config/Containerfile
  15. 20
      qemu-user-static/config/container-entrypoint
  16. 11
      qemu-user-static/qemu-user-static-build.timer
  17. 10
      qemu-user-static/qemu-user-static.build
  18. 26
      qemu-user-static/qemu-user-static.container
  19. 11
      qemu-user-static/qemu-user-static.target
  20. 3
      virtiofs/Makefile
  21. 22
      virtiofs/backup-virtiofs.service
  22. 14
      virtiofs/fcos.bu
  23. 16
      virtiofs/restore-virtiofs.service

4
Makefile

@ -3,6 +3,8 @@ SUBDIRS := $(dir $(SUBDIRS))
.PHONY: all help butane clean dryrun fcos-vm clean-vm uninstall $(SUBDIRS) .PHONY: all help butane clean dryrun fcos-vm clean-vm uninstall $(SUBDIRS)
export I_KNOW_WHAT_I_AM_DOING ?= no
all: help all: help
help: help:
@echo "Available targets:" @echo "Available targets:"
@ -16,6 +18,8 @@ help:
dryrun: $(SUBDIRS) dryrun: $(SUBDIRS)
butane: $(SUBDIRS) butane: $(SUBDIRS)
clean: $(SUBDIRS) clean: $(SUBDIRS)
rm -f local.ign
fcos-vm: $(SUBDIRS) fcos-vm: $(SUBDIRS)
clean-vm: $(SUBDIRS) clean-vm: $(SUBDIRS)
uninstall: $(SUBDIRS) uninstall: $(SUBDIRS)

168
Makefile.common

@ -1,6 +1,19 @@
all: help all: help
help: help:
@echo
@echo "================================================"
@echo " Project '$(PROJECT_NAME)'"
@echo "================================================"
@echo
@echo "Relevant paths and settings:"
@echo
@echo " Configuration directory: /etc/quadlets/$(PROJECT_NAME)"
@echo " Persistent Storage directory: /var/lib/quadlets/$(PROJECT_NAME)"
@echo " UID & GID for project files: $(PROJECT_UID):$(PROJECT_GID)"
@echo " Dependencies: $(if $(DEPENDENCIES),$(DEPENDENCIES),none)"
@echo
@echo "Available targets:" @echo "Available targets:"
@echo
@echo " help - Show this help message" @echo " help - Show this help message"
@echo " install - Install quadlets and systemd units" @echo " install - Install quadlets and systemd units"
@echo " uninstall - Uninstall quadlets and systemd units" @echo " uninstall - Uninstall quadlets and systemd units"
@ -9,11 +22,35 @@ help:
@echo " tail-logs - Tail the logs of the quadlet units" @echo " tail-logs - Tail the logs of the quadlet units"
@echo " butane - Build Butane specifications suitable for Fedora CoreOS" @echo " butane - Build Butane specifications suitable for Fedora CoreOS"
@echo " fcos-vm - Launch a Fedora CoreOS VM with the generated Butane spec" @echo " fcos-vm - Launch a Fedora CoreOS VM with the generated Butane spec"
@echo " clean-vm - Clean up the Fedora CoreOS VM and its resources" @echo " clean-vm - Clean up the Fedora CoreOS VM but keep its storage resources"
@echo " remove-vm - Remove all resources related to the Fedora CoreOS VM"
@echo " console - Connect to the Fedora CoreOS VM console" @echo " console - Connect to the Fedora CoreOS VM console"
@echo
# Where to install the quadlets and systemd units. If not set, the host system is used. @echo "Useful commands:"
TARGET_CHROOT ?= @echo
@echo " 1. make uninstall install # Replace quadlets and systemd units"
@echo " 2. make uninstall clean install # Same but also remove persistent data and configuration"
@echo " 3. make uninstall install tail-logs # Replace quadlets and systemd units, then tail their logs"
@echo " 4. make I_KNOW_WHAT_I_AM_DOING=yes clean # Remove all persistent data and configuration without confirmation"
@echo " 5. make butane # Build Butane specifications suitable for Fedora CoreOS"
@echo " 6. make fcos-vm console # Launch a fresh Fedora CoreOS VM (while retaining its persistent data) and connect to its console"
@echo " 7. make remove-vm # Remove all resources related to the Fedora CoreOS VM"
@echo
@echo "All-in-one commands:"
@echo
@echo " 1. make I_KNOW_WHAT_I_AM_DOING=yes uninstall clean install tail-logs"
@echo " 2. make fcos-vm console"
@echo
# Create a temporary directory as target chroot when we detect that we are building Butane specs or launching a Fedora CoreOS VM.
ifneq ($(filter %.ign %.bu butane fcos-vm,$(MAKECMDGOALS)),)
ifeq ($(TARGET_CHROOT),)
export TARGET_CHROOT := $(shell mktemp -d /tmp/butane-chroot-XXXXXX)
endif
ifeq ($(BUTANE_BLOCKLIST),)
export BUTANE_BLOCKLIST := $(shell tmp=$$(mktemp /tmp/butane-blocklist-XXXXXX); cp $(TOP_LEVEL_DIR)/butane.blocklist "$$tmp"; echo "$$tmp")
endif
endif
# Name of the current project, derived from the current working directory. # Name of the current project, derived from the current working directory.
# This is used to create subdirectories for configuration and state files. # This is used to create subdirectories for configuration and state files.
@ -67,7 +104,8 @@ DEPENDENCIES ?=
I_KNOW_WHAT_I_AM_DOING ?= I_KNOW_WHAT_I_AM_DOING ?=
# List of all ignition files corresponding to the dependencies # List of all ignition files corresponding to the dependencies
DEPENDENCIES_IGNITION_FILES = $(shell for dep in $(DEPENDENCIES); do echo $(TOP_LEVEL_DIR)/$$dep/$$dep.ign; done) # Here, we inject the "base" project as a dependency. It can therefore be assumed to always be embeddable in project's butane specs.
DEPENDENCIES_IGNITION_FILES := $(shell for dep in base $(DEPENDENCIES); do echo $(TOP_LEVEL_DIR)/$$dep/$$dep.ign $(TOP_LEVEL_DIR)/$$dep/$$dep-examples.ign; done)
# User and group IDs to own the project files and directories. # User and group IDs to own the project files and directories.
PROJECT_UID ?= 0 PROJECT_UID ?= 0
@ -83,6 +121,13 @@ pre-requisites:
echo "This Makefile must be run as root" >&2; \ echo "This Makefile must be run as root" >&2; \
exit 1; \ exit 1; \
fi fi
@set -Eeuo pipefail; \
for tool in install systemctl systemd-analyze systemd-tmpfiles sysctl virt-install virsh qemu-img journalctl coreos-installer resize butane yq; do \
if ! which $$tool &>/dev/null ; then \
echo "$$tool is not installed. Please install it first." >&2; \
exit 1; \
fi ; \
done
# Perform a dry run of the podman systemd generator to validate the quadlet and systemd files. # Perform a dry run of the podman systemd generator to validate the quadlet and systemd files.
dryrun: dryrun:
@ -109,6 +154,7 @@ $(TARGET_CONFIG_FILES): $(TARGET_CHROOT)/etc/quadlets/$(PROJECT_NAME)/%: config/
$(TARGET_EXAMPLES_CONFIG_FILES): $(TARGET_CHROOT)/etc/quadlets/$(PROJECT_NAME)/%: config/examples/% $(TARGET_CHROOT)/etc/quadlets/$(PROJECT_NAME) $(TARGET_EXAMPLES_CONFIG_FILES): $(TARGET_CHROOT)/etc/quadlets/$(PROJECT_NAME)/%: config/examples/% $(TARGET_CHROOT)/etc/quadlets/$(PROJECT_NAME)
$(filter-out %.env, $(TARGET_CONFIG_FILES) $(TARGET_EXAMPLES_CONFIG_FILES)): $(filter-out %.env, $(TARGET_CONFIG_FILES) $(TARGET_EXAMPLES_CONFIG_FILES)):
@run() { echo $$*; "$$@"; }; \ @run() { echo $$*; "$$@"; }; \
set -Eeuo pipefail; \
if [ -x $< ]; then \ if [ -x $< ]; then \
run install -D -m 0755 -o $(PROJECT_UID) -g $(PROJECT_GID) $< $@; \ run install -D -m 0755 -o $(PROJECT_UID) -g $(PROJECT_GID) $< $@; \
else \ else \
@ -149,6 +195,7 @@ install-files: install-files-pre install-config install-examples
# This target can be extended by Makefiles sourcing this one. # This target can be extended by Makefiles sourcing this one.
install-files-pre:: install-files-pre::
@run() { echo $$*; "$$@"; }; \ @run() { echo $$*; "$$@"; }; \
set -Eeuo pipefail; \
for dep in $(DEPENDENCIES); do \ for dep in $(DEPENDENCIES); do \
run $(MAKE) -C $(TOP_LEVEL_DIR)/$$dep install-files; \ run $(MAKE) -C $(TOP_LEVEL_DIR)/$$dep install-files; \
done done
@ -162,6 +209,7 @@ install-actions: install-actions-pre
systemctl daemon-reload systemctl daemon-reload
systemd-analyze --generators=true verify $(QUADLET_UNIT_NAMES) $(SYSTEMD_UNIT_NAMES) systemd-analyze --generators=true verify $(QUADLET_UNIT_NAMES) $(SYSTEMD_UNIT_NAMES)
@run() { echo $$*; "$$@"; }; \ @run() { echo $$*; "$$@"; }; \
set -Eeuo pipefail; \
if [ -f /etc/tmpfiles.d/$(PROJECT_NAME).conf ]; then \ if [ -f /etc/tmpfiles.d/$(PROJECT_NAME).conf ]; then \
run systemd-tmpfiles --create /etc/tmpfiles.d/$(PROJECT_NAME).conf; \ run systemd-tmpfiles --create /etc/tmpfiles.d/$(PROJECT_NAME).conf; \
fi; \ fi; \
@ -176,6 +224,7 @@ install-actions: install-actions-pre
# This target can be extended by Makefiles sourcing this one. # This target can be extended by Makefiles sourcing this one.
install-actions-pre:: install-actions-pre::
@run() { echo $$*; "$$@"; }; \ @run() { echo $$*; "$$@"; }; \
set -Eeuo pipefail; \
for dep in $(DEPENDENCIES); do \ for dep in $(DEPENDENCIES); do \
run $(MAKE) -C $(TOP_LEVEL_DIR)/$$dep install-actions; \ run $(MAKE) -C $(TOP_LEVEL_DIR)/$$dep install-actions; \
done done
@ -203,6 +252,7 @@ uninstall: pre-requisites uninstall-pre
systemctl disable $(SYSTEMD_MAIN_UNIT_NAMES) $(SYSTEMD_TIMER_NAMES) || true systemctl disable $(SYSTEMD_MAIN_UNIT_NAMES) $(SYSTEMD_TIMER_NAMES) || true
systemctl stop $(SYSTEMD_UNIT_NAMES) $(QUADLET_UNIT_NAMES) || true systemctl stop $(SYSTEMD_UNIT_NAMES) $(QUADLET_UNIT_NAMES) || true
@run() { echo $$*; "$$@"; }; \ @run() { echo $$*; "$$@"; }; \
set -Eeuo pipefail; \
if [ -f /etc/tmpfiles.d/$(PROJECT_NAME).conf ]; then \ if [ -f /etc/tmpfiles.d/$(PROJECT_NAME).conf ]; then \
run systemd-tmpfiles --purge /etc/tmpfiles.d/$(PROJECT_NAME).conf; \ run systemd-tmpfiles --purge /etc/tmpfiles.d/$(PROJECT_NAME).conf; \
fi fi
@ -218,6 +268,7 @@ uninstall-pre::
# This target can be extended by Makefiles sourcing this one. # This target can be extended by Makefiles sourcing this one.
uninstall-post:: uninstall-post::
@run() { echo $$*; "$$@"; }; \ @run() { echo $$*; "$$@"; }; \
set -Eeuo pipefail; \
for dep in $(DEPENDENCIES); do \ for dep in $(DEPENDENCIES); do \
run $(MAKE) -C $(TOP_LEVEL_DIR)/$$dep uninstall; \ run $(MAKE) -C $(TOP_LEVEL_DIR)/$$dep uninstall; \
done done
@ -225,67 +276,68 @@ uninstall-post::
# Tail the logs of all units managed by this project. # Tail the logs of all units managed by this project.
tail-logs: pre-requisites tail-logs: pre-requisites
@run() { echo $$*; "$$@"; }; \ @run() { echo $$*; "$$@"; }; \
set -Eeuo pipefail; \
declare -a journalctl_args=( -f ); \ declare -a journalctl_args=( -f ); \
for unit in $$($(MAKE) -s units 2>/dev/null | sort -u); do \ for unit in $$($(MAKE) -s units 2>/dev/null | sort -u); do \
journalctl_args+=( -u "$$unit" ); \ journalctl_args+=( -u "$$unit" ); \
done; \ done; \
run journalctl "$${journalctl_args[@]}" run journalctl "$${journalctl_args[@]}"
# Generate the current project's Butane spec. # Ensure that required variables are set before building Butane specifications.
$(PROJECT_NAME).bu: install-config butane-prerequisites:
@if [ -z "$(TARGET_CHROOT)" ]; then \ @if [ -z "$(TARGET_CHROOT)" ]; then \
echo "TARGET_CHROOT is not set!"; exit 1; \ echo "TARGET_CHROOT is not set!"; exit 1; \
fi; \
if [ -z "$(BUTANE_BLOCKLIST)" ]; then \
echo "BUTANE_BLOCKLIST is not set!"; exit 1; \
fi fi
$(TOP_LEVEL_DIR)/generate-butane-spec.sh $(TARGET_CHROOT) $(TOP_LEVEL_DIR)/butane.blocklist $(SYSTEMD_MAIN_UNIT_NAMES) $(SYSTEMD_TIMER_NAMES) > $(PROJECT_NAME).bu
# Generate the current project's Butane spec for the example configuration files. # Build the Butane specifications (configuration files) suitable for Fedora CoreOS.
$(PROJECT_NAME)-examples.bu: install-examples # In order to avoid duplications in the ignition files, a blocklist is updated, containing file paths as they are added to the chroot.
@if [ -z "$(TARGET_CHROOT)" ]; then \ $(PROJECT_NAME).bu: butane-prerequisites install-config
echo "TARGET_CHROOT is not set!"; exit 1; \ $(TOP_LEVEL_DIR)/generate-butane-spec.sh $(TARGET_CHROOT) $(BUTANE_BLOCKLIST) $(SYSTEMD_MAIN_UNIT_NAMES) $(SYSTEMD_TIMER_NAMES) > $(PROJECT_NAME).bu
fi @(cat $(TOP_LEVEL_DIR)/butane.blocklist; echo; for file in $$(find "$$TARGET_CHROOT"); do echo "$${file#$$TARGET_CHROOT}"; done) | sort -u | grep -v -E '^$$' > "$(BUTANE_BLOCKLIST)"
$(TOP_LEVEL_DIR)/generate-butane-spec.sh $(TARGET_CHROOT) butane.blocklist > $(PROJECT_NAME)-examples.bu
# Generate the current project's Ignition files from the Butane specs. # Build the Butane specifications (example files) suitable for Fedora CoreOS.
$(PROJECT_NAME).ign: butane # In order to avoid duplications in the ignition files, a blocklist is updated, containing file paths as they are added to the chroot.
butane --strict -o $(PROJECT_NAME).ign $(PROJECT_NAME).bu $(PROJECT_NAME)-examples.bu: butane-prerequisites install-examples
butane --strict -o $(PROJECT_NAME)-examples.ign $(PROJECT_NAME)-examples.bu $(TOP_LEVEL_DIR)/generate-butane-spec.sh $(TARGET_CHROOT) $(BUTANE_BLOCKLIST) > $(PROJECT_NAME)-examples.bu
@(cat $(TOP_LEVEL_DIR)/butane.blocklist; echo; for file in $$(find "$$TARGET_CHROOT"); do echo "$${file#$$TARGET_CHROOT}"; done) | sort -u | grep -v -E '^$$' > "$(BUTANE_BLOCKLIST)"
# Build the Butane specifications suitable for Fedora CoreOS, including those of the dependencies of this project. # Build the Butane specifications + Ignition files suitable for Fedora CoreOS of the dependencies of this project.
# In order to avoid duplications in the ignition files, a blocklist is created containing file paths as they are added to the chroot. butane-pre:: butane-prerequisites
butane:
@run() { echo $$*; "$$@"; }; \ @run() { echo $$*; "$$@"; }; \
init_butane_blocklist() { \ set -Eeuo pipefail; \
(cat $(TOP_LEVEL_DIR)/butane.blocklist; echo; for file in $$(find "$$TARGET_CHROOT"); do echo "$${file#$$TARGET_CHROOT}"; done) | sort -u | grep -v -E '^$$' > butane.blocklist; \ for dep in base $(DEPENDENCIES); do \
}; \ if [[ "$$dep" == "$(PROJECT_NAME)" ]]; then \
if [ -z "$(TARGET_CHROOT)" ]; then \ # Avoid building the current project as its own dependency. \
TARGET_CHROOT=$$(mktemp -d /tmp/butane-XXXXXX); \ continue; \
else \
TARGET_CHROOT="$(TARGET_CHROOT)"; \
fi ; \ fi ; \
for dep in $(DEPENDENCIES); do \ run $(MAKE) -C $(TOP_LEVEL_DIR)/$$dep $$dep.ign $$dep-examples.ign ; \
run $(MAKE) -C $(TOP_LEVEL_DIR)/$$dep TARGET_CHROOT="$$TARGET_CHROOT" butane ; \ done
done ; \
run init_butane_blocklist ; \ # Generate the current project's Ignition files from the Butane specs.
run $(MAKE) TARGET_CHROOT="$$TARGET_CHROOT" $(PROJECT_NAME).bu; \ $(PROJECT_NAME).ign $(PROJECT_NAME)-examples.ign: butane-pre
run init_butane_blocklist ; \ $(PROJECT_NAME).ign $(PROJECT_NAME)-examples.ign: %.ign: %.bu
run $(MAKE) TARGET_CHROOT="$$TARGET_CHROOT" $(PROJECT_NAME)-examples.bu; \ butane --strict -o $@ $<
if [ -z "$(TARGET_CHROOT)" ]; then \
run rm -rf "$$TARGET_CHROOT"; \ # Build the Butane specifications + Ignition files suitable for Fedora CoreOS, including those of the dependencies of this project.
fi butane: fcos.ign
# Generate the local Butane spec (the one containing local customizations). # Generate the local Butane spec + Ignition file (the one containing local customizations).
$(TOP_LEVEL_DIR)/local.ign: $(TOP_LEVEL_DIR)/local.bu $(TOP_LEVEL_DIR)/local.ign: $(TOP_LEVEL_DIR)/local.bu
butane --strict -o $@ $< butane --strict -o $@ $<
# Build the ignition files of the dependencies of this project. # Build the ignition files of the dependencies of this project.
$(DEPENDENCIES_IGNITION_FILES): $(DEPENDENCIES_IGNITION_FILES):
$(MAKE) -C $(dir $@) $(notdir $@) $(MAKE) -C $(dir $@) $(notdir $@)
# Because we don't know how to build this file, it is safer to declare it as phony and let the Makefile of the dependency handle it. # The file might exist already, declare it as phony and let the child Makefile handle it.
.PHONY: $(DEPENDENCIES_IGNITION_FILES) .PHONY: $(DEPENDENCIES_IGNITION_FILES)
# Generate the final Fedora CoreOS ignition file by merging the Butane spec with the local and project-specific ignition files, as well as those of the dependencies. # Generate the final Fedora CoreOS ignition file by merging the Butane spec with the local and project-specific ignition files, as well as those of the dependencies.
fcos.ign: fcos.bu $(TOP_LEVEL_DIR)/local.ign $(PROJECT_NAME).ign $(DEPENDENCIES_IGNITION_FILES) fcos.ign: fcos.bu $(TOP_LEVEL_DIR)/local.ign $(PROJECT_NAME).ign $(PROJECT_NAME)-examples.ign $(DEPENDENCIES_IGNITION_FILES)
@run() { echo $$*; "$$@"; }; \ @run() { echo $$*; "$$@"; }; \
set -Eeuo pipefail; \
tmp=$$(mktemp -d /tmp/butane-XXXXXX); \ tmp=$$(mktemp -d /tmp/butane-XXXXXX); \
run cp $(filter %.ign,$^) $$tmp; \ run cp $(filter %.ign,$^) $$tmp; \
run butane --strict -d $$tmp -o $@ fcos.bu; \ run butane --strict -d $$tmp -o $@ fcos.bu; \
@ -294,6 +346,7 @@ fcos.ign: fcos.bu $(TOP_LEVEL_DIR)/local.ign $(PROJECT_NAME).ign $(DEPENDENCIES_
# Fetch the latest version of the Fedora CoreOS QCOW2 image. # Fetch the latest version of the Fedora CoreOS QCOW2 image.
/var/lib/libvirt/images/library/fedora-coreos.qcow2: /var/lib/libvirt/images/library/fedora-coreos.qcow2:
@run() { echo $$*; "$$@"; }; \ @run() { echo $$*; "$$@"; }; \
set -Eeuo pipefail; \
run mkdir -p /var/lib/libvirt/images/library/ ; \ run mkdir -p /var/lib/libvirt/images/library/ ; \
if ! run coreos-installer download -p qemu -f qcow2.xz -d -C /var/lib/libvirt/images/library/ ; then \ if ! run coreos-installer download -p qemu -f qcow2.xz -d -C /var/lib/libvirt/images/library/ ; then \
echo "CoreOS QCOW2 image could not be downloaded." >&2; \ echo "CoreOS QCOW2 image could not be downloaded." >&2; \
@ -310,31 +363,50 @@ fcos.ign: fcos.bu $(TOP_LEVEL_DIR)/local.ign $(PROJECT_NAME).ign $(DEPENDENCIES_
/var/lib/libvirt/images/fcos-$(PROJECT_NAME)/root.qcow2: /var/lib/libvirt/images/library/fedora-coreos.qcow2 /var/lib/libvirt/images/fcos-$(PROJECT_NAME)/root.qcow2: /var/lib/libvirt/images/library/fedora-coreos.qcow2
install -D -o root -g root -m 0644 $< $@ install -D -o root -g root -m 0644 $< $@
# Create an empty QCOW2 image for the /var filesystem of the VM.
/var/lib/libvirt/images/fcos-$(PROJECT_NAME)/var.qcow2:
qemu-img create -f qcow2 $@ 100G
# Create the directory to be shared with the Fedora CoreOS VM through virtiofs. # Create the directory to be shared with the Fedora CoreOS VM through virtiofs.
/srv/fcos-$(PROJECT_NAME): /srv/fcos-$(PROJECT_NAME):
install -d -o root -g root -m 0755 $@ install -d -o root -g root -m 0755 $@
# Launch a Fedora CoreOS VM with the generated Butane spec. # Launch a Fedora CoreOS VM with the generated Butane spec.
fcos-vm: pre-requisites clean-vm /var/lib/libvirt/images/fcos-$(PROJECT_NAME)/fcos.ign /var/lib/libvirt/images/fcos-$(PROJECT_NAME)/root.qcow2 /srv/fcos-$(PROJECT_NAME) fcos-vm: pre-requisites clean-vm /var/lib/libvirt/images/fcos-$(PROJECT_NAME)/fcos.ign /var/lib/libvirt/images/fcos-$(PROJECT_NAME)/root.qcow2 /var/lib/libvirt/images/fcos-$(PROJECT_NAME)/var.qcow2 /srv/fcos-$(PROJECT_NAME)
virt-install --name=fcos-$(PROJECT_NAME) --import --noautoconsole \ virt-install --name=fcos-$(PROJECT_NAME) --import --noautoconsole \
--ram=4096 --vcpus=2 --os-variant=fedora-coreos-stable \ --ram=4096 --vcpus=2 --os-variant=fedora-coreos-stable \
--disk path=/var/lib/libvirt/images/fcos-$(PROJECT_NAME)/root.qcow2,format=qcow2,size=50 \ --disk path=/var/lib/libvirt/images/fcos-$(PROJECT_NAME)/root.qcow2,format=qcow2,size=50 \
--disk path=/var/lib/libvirt/images/fcos-$(PROJECT_NAME)/var.qcow2,format=qcow2 \
--qemu-commandline="-fw_cfg name=opt/com.coreos/config,file=/var/lib/libvirt/images/fcos-$(PROJECT_NAME)/fcos.ign" \ --qemu-commandline="-fw_cfg name=opt/com.coreos/config,file=/var/lib/libvirt/images/fcos-$(PROJECT_NAME)/fcos.ign" \
--network network=default,model=virtio \ --network network=default,model=virtio \
--console=pty,target.type=virtio --serial=pty --graphics=none --boot=uefi \ --console=pty,target.type=virtio --serial=pty --graphics=none --boot=uefi \
--memorybacking=access.mode=shared,source.type=memfd \ --memorybacking=access.mode=shared,source.type=memfd \
--filesystem=type=mount,accessmode=passthrough,driver.type=virtiofs,driver.queue=1024,source.dir=/srv/fcos-$(PROJECT_NAME),target.dir=data --filesystem=type=mount,accessmode=passthrough,driver.type=virtiofs,driver.queue=1024,source.dir=/srv/fcos-$(PROJECT_NAME),target.dir=data
# Clean up the Fedora CoreOS VM and its resources. # Clean up the Fedora CoreOS VM but keep its storage resources.
clean-vm: pre-requisites clean-vm: pre-requisites
virsh destroy fcos-$(PROJECT_NAME) || true virsh destroy fcos-$(PROJECT_NAME) || true
virsh undefine fcos-$(PROJECT_NAME) --nvram || true virsh undefine fcos-$(PROJECT_NAME) --nvram || true
rm -f /var/lib/libvirt/images/fcos-$(PROJECT_NAME)/root.qcow2 /var/lib/libvirt/images/fcos-$(PROJECT_NAME)/fcos.ign
# Remove all resources related to the Fedora CoreOS VM.
remove-vm: clean-vm
rm -rf /var/lib/libvirt/images/fcos-$(PROJECT_NAME) rm -rf /var/lib/libvirt/images/fcos-$(PROJECT_NAME)
rm -rf /srv/fcos-$(PROJECT_NAME) rm -rf /srv/fcos-$(PROJECT_NAME)
# Connect to the console of the Fedora CoreOS VM. # Connect to the console of the Fedora CoreOS VM.
console: pre-requisites console: pre-requisites
@while sleep 2; do virsh console fcos-$(PROJECT_NAME); echo -e "Disconnected. Reconnecting in 2 seconds...\nPress Ctrl-C to abort.\n"; done @set -Eeuo pipefail; \
# Save the current terminal size to restore it after disconnecting from the VM console. \
term_size=$$(stty size); \
while sleep 2; do \
virsh console fcos-$(PROJECT_NAME); \
# Restore the terminal size after disconnecting from the VM console. \
# This avoids issues with the terminal being stuck in an incorrect size because \
# of the UEFI / Grub TUI messed with the terminal size during a VM reboot. \
eval $$(resize -s $$term_size); \
echo -e "Disconnected. Reconnecting in 2 seconds...\nPress Ctrl-C to abort.\n"; \
done
# List all systemd and quadlet unit names provided by the dependencies of this project. # List all systemd and quadlet unit names provided by the dependencies of this project.
units-pre:: units-pre::
@ -350,6 +422,7 @@ units: units-pre
# This target can be extended by Makefiles sourcing this one. # This target can be extended by Makefiles sourcing this one.
clean-pre:: clean-pre::
@run() { echo $$*; "$$@"; }; \ @run() { echo $$*; "$$@"; }; \
set -Eeuo pipefail; \
for dep in $(DEPENDENCIES); do \ for dep in $(DEPENDENCIES); do \
run $(MAKE) -C $(TOP_LEVEL_DIR)/$$dep clean; \ run $(MAKE) -C $(TOP_LEVEL_DIR)/$$dep clean; \
done done
@ -360,8 +433,9 @@ clean-post::
# Remove all persistent data and configuration files # Remove all persistent data and configuration files
clean: clean-pre pre-requisites clean: clean-pre pre-requisites
rm -f *.butane rm -f *.bu *.ign butane.blocklist
@run() { echo $$*; "$$@"; }; \ @run() { echo $$*; "$$@"; }; \
set -Eeuo pipefail; \
if [ "$(I_KNOW_WHAT_I_AM_DOING)" != "yes" ]; then \ if [ "$(I_KNOW_WHAT_I_AM_DOING)" != "yes" ]; then \
read -p "This will remove all data of '$(PROJECT_NAME)'. Are you sure? (only 'yes' is accepted) " ans; \ read -p "This will remove all data of '$(PROJECT_NAME)'. Are you sure? (only 'yes' is accepted) " ans; \
if [ "$$ans" != "yes" ] && [ "$$ans" != "YES" ]; then \ if [ "$$ans" != "yes" ] && [ "$$ans" != "YES" ]; then \
@ -373,7 +447,7 @@ clean: clean-pre pre-requisites
# All phony targets # All phony targets
.PHONY: all install install-config install-examples uninstall pre-requisites clean dryrun .PHONY: all install install-config install-examples uninstall pre-requisites clean dryrun
.PHONY: tail-logs butane help fcos-vm clean-vm console units units-pre .PHONY: tail-logs butane help fcos-vm clean-vm console units units-pre remove-vm
.PHONY: clean-pre clean-post install-pre install-post uninstall-pre uninstall-post .PHONY: clean-pre clean-post install-pre install-post uninstall-pre uninstall-post
.PHONY: install-files install-files-pre install-files-post install-actions .PHONY: install-files install-files-pre install-files-post install-actions
.PHONY: install-actions-pre install-actions-post .PHONY: install-actions-pre install-actions-post butane-prerequisites butane-pre

3
base/Makefile

@ -0,0 +1,3 @@
TOP_LEVEL_DIR := ..
include $(TOP_LEVEL_DIR)/Makefile.common
SYSTEMD_MAIN_UNIT_NAMES := var-lib-virtiofs-data.mount rpm-ostree-install-qemu-guest-agent.service

20
base/rpm-ostree-install-qemu-guest-agent.service

@ -0,0 +1,20 @@
[Unit]
Description=Install qemu-guest-agent
Wants=network-online.target
After=network-online.target
Before=zincati.service
ConditionPathExists=!/usr/bin/qemu-ga
# Only run on Fedora CoreOS
ConditionOSRelease=ID=fedora
ConditionOSRelease=VARIANT_ID=coreos
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/rpm-ostree install -y --allow-inactive qemu-guest-agent
ExecStart=/usr/bin/rpm-ostree apply-live
ExecStart=/usr/bin/systemctl enable --now qemu-guest-agent.service
[Install]
WantedBy=multi-user.target

0
virtiofs/tmpfiles.d/virtiofs.conf → base/tmpfiles.d/base.conf

4
virtiofs/var-lib-virtiofs-data.mount → base/var-lib-virtiofs-data.mount

@ -1,9 +1,5 @@
[Unit] [Unit]
Description=Mount the "data" virtio filesystem Description=Mount the "data" virtio filesystem
After=backup-virtiofs.service
Requires=backup-virtiofs.service
Before=restore-virtiofs.service
Wants=restore-virtiofs.service
# Only run on Fedora CoreOS # Only run on Fedora CoreOS
ConditionOSRelease=ID=fedora ConditionOSRelease=ID=fedora

41
local.bu.template

@ -1,5 +1,46 @@
variant: fcos variant: fcos
version: 1.4.0 version: 1.4.0
storage:
disks:
- device: /dev/vdb
wipe_table: false
partitions:
# Specify the partition number so that FCOS do not try to create a new
# partition at each VM redeployment.
- number: 1
size_mib: 0
start_mib: 0
label: var
filesystems:
- path: /var
device: /dev/disk/by-partlabel/var
format: xfs
with_mount_unit: true
directories:
- path: /var/lib/private/sshd
mode: 0700
files:
- path: /etc/resolv.conf
overwrite: true
contents:
inline: "" # will be updated by NetworkManager
- path: /etc/NetworkManager/conf.d/itix.conf
contents:
inline: |
[main]
# test
rc-manager=file
systemd:
units:
- name: systemd-resolved.service
enabled: false
mask: true
- name: sshd-keygen@.service
dropins:
- name: backup-restore.conf
contents: |
[Service]
ExecStartPost=/bin/bash -c 'if [ -f /var/lib/private/sshd/ssh_host_%i_key ]; then cp -Z /var/lib/private/sshd/ssh_host_%i_key{,.pub} /etc/ssh/; elif [ -f /etc/ssh/ssh_host_%i_key ]; then cp -a /etc/ssh/ssh_host_%i_key{,.pub} /var/lib/private/sshd/; fi'
passwd: passwd:
users: users:
- name: core - name: core

1
nextcloud/Makefile

@ -2,7 +2,6 @@
## Makefile for PostgreSQL quadlet ## Makefile for PostgreSQL quadlet
## ##
# Project dependencies: Nextcloud also depends on virtiofs for data storage but is a transitive dependency via postgresql
DEPENDENCIES = postgresql DEPENDENCIES = postgresql
# Nextcloud quadlet is mapped to the 10008 user (nextcloud) and 10000 group (itix-svc) # Nextcloud quadlet is mapped to the 10008 user (nextcloud) and 10000 group (itix-svc)

11
nextcloud/fcos.bu

@ -1,11 +0,0 @@
variant: fcos
version: 1.4.0
ignition:
config:
merge:
- local: virtiofs.ign
- local: nextcloud.ign
- local: nextcloud-examples.ign
- local: postgresql.ign
- local: postgresql-examples.ign
- local: local.ign

8
nginx/fcos.bu

@ -1,8 +0,0 @@
variant: fcos
version: 1.4.0
ignition:
config:
merge:
- local: nginx.ign
- local: nginx-examples.ign
- local: local.ign

3
postgresql/Makefile

@ -2,9 +2,6 @@
## Makefile for PostgreSQL quadlet ## Makefile for PostgreSQL quadlet
## ##
# Project dependencies
DEPENDENCIES = virtiofs
# PostgreSQL quadlet is mapped to the 10004 user (postgres) and 10000 group (itix-svc) # PostgreSQL quadlet is mapped to the 10004 user (postgres) and 10000 group (itix-svc)
PROJECT_UID = 10004 PROJECT_UID = 10004
PROJECT_GID = 10000 PROJECT_GID = 10000

9
postgresql/fcos.bu

@ -1,9 +0,0 @@
variant: fcos
version: 1.4.0
ignition:
config:
merge:
- local: virtiofs.ign
- local: postgresql.ign
- local: postgresql-examples.ign
- local: local.ign

8
qemu-user-static/Makefile

@ -0,0 +1,8 @@
TOP_LEVEL_DIR := ..
include $(TOP_LEVEL_DIR)/Makefile.common
.PHONY: test
test: uninstall clean install
@echo "Running $(PROJECT_NAME) tests..."
curl -sSfL -I http://localhost/

9
qemu-user-static/config/Containerfile

@ -0,0 +1,9 @@
FROM quay.io/fedora/fedora:42
RUN dnf install -y qemu-user-static \
&& dnf clean all
ADD container-entrypoint /
ENTRYPOINT ["/container-entrypoint"]
CMD []

20
qemu-user-static/config/container-entrypoint

@ -0,0 +1,20 @@
#!/bin/sh
set -Eeuo pipefail
if [ ! -d /proc/sys/fs/binfmt_misc ]; then
echo "No binfmt support in the kernel."
echo " Try: '/sbin/modprobe binfmt_misc' from the host"
exit 1
fi
if [ ! -f /proc/sys/fs/binfmt_misc/register ]; then
echo "Mounting /proc/sys/fs/binfmt_misc..."
mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
fi
echo "Cleaning up..."
find /proc/sys/fs/binfmt_misc -type f -name 'qemu-*' -exec sh -c 'echo -1 > {}' \;
echo "Registering..."
exec /usr/lib/systemd/systemd-binfmt

11
qemu-user-static/qemu-user-static-build.timer

@ -0,0 +1,11 @@
[Unit]
Description=multiarch /usr/bin/qemu-*-static
Documentation=https://github.com/multiarch/qemu-user-static
PartOf=qemu-user-static.target
[Timer]
OnCalendar=weekly
Persistent=true
[Install]
WantedBy=qemu-user-static.target

10
qemu-user-static/qemu-user-static.build

@ -0,0 +1,10 @@
[Unit]
Description=multiarch /usr/bin/qemu-*-static
Documentation=https://github.com/multiarch/qemu-user-static
Wants=network-online.target
After=network-online.target
[Build]
File=/etc/quadlets/qemu-user-static/Containerfile
ImageTag=localhost/qemu-user-static:latest
SetWorkingDirectory=/etc/quadlets/qemu-user-static

26
qemu-user-static/qemu-user-static.container

@ -0,0 +1,26 @@
[Unit]
Description=multiarch /usr/bin/qemu-*-static
Documentation=https://github.com/multiarch/qemu-user-static
Wants=qemu-user-static-build.service
After=qemu-user-static-build.service
PartOf=qemu-user-static.target
[Service]
Type=oneshot
RemainAfterExit=yes
[Container]
ContainerName=qemu-user-static
# Image
Image=localhost/qemu-user-static:latest
AutoUpdate=local
# Security
PodmanArgs=--privileged
SecurityLabelFileType=container_file_t
SecurityLabelType=spc_t
SecurityLabelLevel=s0
[Install]
WantedBy=qemu-user-static.target

11
qemu-user-static/qemu-user-static.target

@ -0,0 +1,11 @@
[Unit]
Description=qemu-user-static Service Target
Documentation=man:systemd.target(5)
Requires=qemu-user-static.service qemu-user-static-build.timer
After=qemu-user-static.service qemu-user-static-build.timer
# Allow isolation - can stop/start this target independently
AllowIsolate=yes
[Install]
WantedBy=multi-user.target

3
virtiofs/Makefile

@ -1,3 +0,0 @@
TOP_LEVEL_DIR := ..
include $(TOP_LEVEL_DIR)/Makefile.common
SYSTEMD_MAIN_UNIT_NAMES := var-lib-virtiofs-data.mount

22
virtiofs/backup-virtiofs.service

@ -1,22 +0,0 @@
[Unit]
Description=Backup the "data" virtio filesystems
Before=var-lib-virtiofs-data.mount
RequiresMountsFor=/var
ConditionPathIsMountPoint=!/var/lib/virtiofs/data
# Unless DefaultDependencies= is set to false, service units will implicitly
# have dependencies of type Requires= and After= on basic.target as well as
# dependencies of type Conflicts= and Before= on shutdown.target.
#
# So, we need to set DefaultDependencies to "no" to break the ordering cycle.
DefaultDependencies=no
# Only run on Fedora CoreOS
ConditionOSRelease=ID=fedora
ConditionOSRelease=VARIANT_ID=coreos
[Service]
Type=oneshot
UMask=077
ExecStart=/bin/bash -Eeuo pipefail -c 'if grep -q "data /var/lib/virtiofs/data" /proc/mounts; then echo "ERROR: /var/lib/virtiofs/data is mounted!"; exit 1; else tar -cf /var/lib/private/virtiofs.tar -C /var/lib/virtiofs/data .; fi'
RemainAfterExit=yes

14
virtiofs/fcos.bu

@ -1,14 +0,0 @@
variant: fcos
version: 1.4.0
ignition:
config:
merge:
- local: virtiofs.ign
- local: local.ign
storage:
files:
- path: "/var/lib/virtiofs/data/witness.txt"
mode: 0644
contents:
inline: |
Hello, World!

16
virtiofs/restore-virtiofs.service

@ -1,16 +0,0 @@
[Unit]
Description=Restore the "data" virtio filesystems
After=var-lib-virtiofs-data.mount
Requires=var-lib-virtiofs-data.mount
RequiresMountsFor=/var
ConditionPathIsMountPoint=/var/lib/virtiofs/data
ConditionPathExists=/var/lib/private/virtiofs.tar
# Only run on Fedora CoreOS
ConditionOSRelease=ID=fedora
ConditionOSRelease=VARIANT_ID=coreos
[Service]
Type=oneshot
ExecStart=/bin/bash -Eeuo pipefail -c 'if ! grep -q "data /var/lib/virtiofs/data" /proc/mounts; then echo "ERROR: /var/lib/virtiofs/data is NOT mounted!"; exit 1; else tar -xf /var/lib/private/virtiofs.tar -C /var/lib/virtiofs/data; rm -f /var/lib/private/virtiofs.tar; fi'
RemainAfterExit=yes
Loading…
Cancel
Save