From cdf76040f17bf7f633de43811ff62c7861bc3aa3 Mon Sep 17 00:00:00 2001 From: librelad Date: Tue, 18 Aug 2026 04:04:23 +0100 Subject: [PATCH] feat(vikunja): add Vikunja; retire Focalboard rather than swap it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Focalboard is the one audit finding with no successor to follow. Mattermost ended support in 2023, the community repo is openly asking for maintainers, and the image has not been rebuilt in 1042 days. Adds Vikunja as the replacement for NEW installs: lists, kanban, table and gantt — the same job Focalboard did — from a project rebuilt 14 days ago. One container on SQLite, no database sidecar, following the catalogue conventions (tag sentinels throughout, category/title + backup.db/backup.files labels, traefik block, gluetun markers). VIKUNJA_SERVICE_PUBLICURL is wired to the existing APP_URL_TAG rather than a hand-built URL. It is not optional for this app — get it wrong and creating the first account fails with a bare "unauthorized" — and APP_URL_TAG already resolves to https:// behind Traefik or http://: otherwise, so the port is never guessed. (First attempt invented a PORT_DATA_1 tag that does not exist; checking what the processors actually emit found the real mechanism, which bookstack already uses.) Focalboard is RETIRED, not deleted. Replacing an app in place would stand still for anyone already running it — their data does not move to Vikunja — so it keeps working, and instead: * the description says plainly that it is unmaintained, why, and what to use instead * UPDATE_TYPE drops to manual, because there is nothing to update TO and auto-pulling a 2.8-year-old tag is pure churn Icon is a drawn placeholder, not the upstream trademark. Co-Authored-By: Claude Opus 5 --- containers/focalboard/focalboard.config | 6 +- containers/vikunja/docker-compose.yml | 60 +++++++++++++++++ containers/vikunja/vikunja.config | 65 +++++++++++++++++++ containers/vikunja/vikunja.svg | 9 +++ .../source/files/arrays/function_manifest.sh | 6 ++ 5 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 containers/vikunja/docker-compose.yml create mode 100644 containers/vikunja/vikunja.config create mode 100644 containers/vikunja/vikunja.svg diff --git a/containers/focalboard/focalboard.config b/containers/focalboard/focalboard.config index 9332212..9a6032c 100755 --- a/containers/focalboard/focalboard.config +++ b/containers/focalboard/focalboard.config @@ -13,7 +13,7 @@ CFG_FOCALBOARD_APP_NAME=focalboard CFG_FOCALBOARD_BACKUP=true CFG_FOCALBOARD_BACKUP_STRATEGY=auto -CFG_FOCALBOARD_UPDATE_TYPE=auto +CFG_FOCALBOARD_UPDATE_TYPE=manual CFG_FOCALBOARD_COMPOSE_FILE=default CFG_FOCALBOARD_HEALTHCHECK=true CFG_FOCALBOARD_AUTHELIA=false @@ -31,8 +31,8 @@ CFG_FOCALBOARD_HEADSCALE=false # CFG_FOCALBOARD_CATEGORY="productivity" CFG_FOCALBOARD_TITLE="Focalboard" -CFG_FOCALBOARD_DESCRIPTION="Project Management" -CFG_FOCALBOARD_LONG_DESCRIPTION="Focalboard is an open source, self-hosted alternative to Trello, Notion, and Asana that helps organize projects and tasks" +CFG_FOCALBOARD_DESCRIPTION="Project Management (unmaintained)" +CFG_FOCALBOARD_LONG_DESCRIPTION="NO LONGER MAINTAINED. Mattermost ended support in 2023 and the community repository is asking for maintainers; the image has not been rebuilt since October 2023, so it receives no security updates. Existing installs keep working and your data is untouched, but for a new board use Vikunja instead. Kept in the catalogue only so current users are not stranded" CFG_FOCALBOARD_URL="https://github.com/mattermost/focalboard" CFG_FOCALBOARD_ACTIONS="configure|install|restart|shutdown|uninstall" diff --git a/containers/vikunja/docker-compose.yml b/containers/vikunja/docker-compose.yml new file mode 100644 index 0000000..0d66cd2 --- /dev/null +++ b/containers/vikunja/docker-compose.yml @@ -0,0 +1,60 @@ +networks: + DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA + external: true + +services: + # Vikunja — tasks, lists, kanban, gantt. One container: the API and the + # frontend were merged upstream, and SQLite is a first-class backend, so + # this needs no database sidecar. + vikunja-service: #LIBREPORTAL|SERVICE_TAG_1|vikunja-service + container_name: vikunja-service + image: vikunja/vikunja:latest #LIBREPORTAL|VIKUNJA_VERSION_TAG|latest + restart: unless-stopped + hostname: vikunja + # GLUETUN_OFF_BEGIN + ports: + - "PORTS_DATA_1" #LIBREPORTAL|PORTS_TAG_1|PORTS_DATA_1 + # GLUETUN_OFF_END + volumes: + - SOCKET_DATA #LIBREPORTAL|SOCKET_TAG|SOCKET_DATA + # The image presets VIKUNJA_DATABASE_PATH=/db/vikunja.db, so the + # database lives in /db and uploaded attachments in files/. + - ./db:/db + - ./files:/app/vikunja/files + environment: + - TZ=TIMEZONE_DATA #LIBREPORTAL|TIMEZONE_TAG|TIMEZONE_DATA + # Vikunja builds absolute URLs from this, and it is NOT optional: + # get it wrong and registering the first account fails with a bare + # "unauthorized". APP_URL_TAG is the existing mechanism for exactly + # this (bookstack uses it too) — it resolves to https:// + # when the app is public and Traefik is installed, and to + # http://: otherwise, so the port never has to + # be guessed or hardcoded here. + - VIKUNJA_SERVICE_PUBLICURL=APP_URL_DATA #LIBREPORTAL|APP_URL_TAG|APP_URL_DATA + - VIKUNJA_DATABASE_TYPE=sqlite + - VIKUNJA_DATABASE_PATH=/db/vikunja.db + labels: + libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA + libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA + libreportal.backup.db: "sqlite:::db/vikunja.db" + libreportal.backup.files: "vikunja-service:/app/vikunja/files:files" + traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA + # TRAEFIK_PORT_1_BEGIN + traefik.http.routers.vikunja-service.entrypoints: web,websecure + traefik.http.routers.vikunja-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1 + traefik.http.routers.vikunja-service.tls: true + traefik.http.routers.vikunja-service.tls.certresolver: production + traefik.http.services.vikunja-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1 + traefik.http.routers.vikunja-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1 + # TRAEFIK_PORT_1_END + traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA + healthcheck: + disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA + # GLUETUN_OFF_BEGIN + networks: + DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA + ipv4_address: IP_DATA_1 #LIBREPORTAL|IP_TAG_1|IP_DATA_1 + # GLUETUN_OFF_END + # GLUETUN_ON_BEGIN + # network_mode: "container:gluetun-service" + # GLUETUN_ON_END diff --git a/containers/vikunja/vikunja.config b/containers/vikunja/vikunja.config new file mode 100644 index 0000000..bc1a63c --- /dev/null +++ b/containers/vikunja/vikunja.config @@ -0,0 +1,65 @@ +# +# ============================================================================= +# GENERAL CONFIGURATION +# ============================================================================= +# APP_NAME = name of application for use in scripts +# COMPOSE_FILE = default for no app_name in the docker-compose file name, app if there is +# BACKUP = if true, include this application in backup operations +# UPDATE_TYPE = auto: new image builds are applied automatically (a recovery snapshot is taken first), manual: only when you press Update +# HEALTHCHECK = if true, default docker health checks for that container will be enabled +# AUTHELIA = if true, use Authelia authentication, if false turned off. +# HEADSCALE = options : false, local, remote (see general config). e.g false or local,remote +# MONITORING = if true, export this app's metrics to Prometheus + Grafana (needs both apps installed) +# +CFG_VIKUNJA_APP_NAME=vikunja +CFG_VIKUNJA_BACKUP=true +CFG_VIKUNJA_BACKUP_STRATEGY=auto +CFG_VIKUNJA_UPDATE_TYPE=auto +CFG_VIKUNJA_COMPOSE_FILE=default +CFG_VIKUNJA_HEALTHCHECK=true +CFG_VIKUNJA_AUTHELIA=false +CFG_VIKUNJA_HEADSCALE=false +CFG_VIKUNJA_MONITORING=false +# +# ============================================================================= +# METADATA +# ============================================================================= +# CATEGORY = application category for grouping +# TITLE = display name for the application +# DESCRIPTION = short description of the application +# LONG_DESCRIPTION = detailed description of the application +# URL = source repository or documentation URL +# ACTIONS = available actions for this application +# +CFG_VIKUNJA_CATEGORY="productivity" +CFG_VIKUNJA_TITLE="Vikunja" +CFG_VIKUNJA_DESCRIPTION="Tasks & Project Management" +CFG_VIKUNJA_LONG_DESCRIPTION="Vikunja organises tasks and projects as lists, kanban boards, tables or a gantt timeline — the same job Focalboard did, from a project that is still actively developed. Runs as a single container on SQLite, with no database sidecar to maintain" +CFG_VIKUNJA_URL="https://vikunja.io" +CFG_VIKUNJA_ACTIONS="configure|install|restart|shutdown|uninstall" +# +# ============================================================================= +# NETWORK CONFIGURATION +# ============================================================================= +# DOMAIN = number of domain from the general config, useful when using multiple domains +# WHITELIST = if true only allow whitelisted ips on traefik, if false allow all +# +CFG_VIKUNJA_DOMAIN=1 +CFG_VIKUNJA_WHITELIST=false +CFG_VIKUNJA_NETWORK=default +# +# ============================================================================= +# PORT CONFIGURATION +# ============================================================================= +# PORT_ = port configuration: app|name|external:internal|access|protocol|login|traefik|webui|description +# - app: application name +# - name: service identifier (webui, dns, ssh, etc.) +# - external:internal: port mapping (external can be 'random' for auto-allocation) +# - access: 'public' (internet accessible), 'private' (local network only), 'disabled' (not running) +# - protocol: 'tcp' or 'udp' +# - login: if true, this port requires basic-auth via Traefik (only meaningful when traefik=true) +# - traefik: if true, Traefik handles this port (reverse proxy) +# - webui: if true, this port serves the main web interface +# - description: human-readable description of the service +# +CFG_VIKUNJA_PORT_1="vikunja-service|webui|random:3456|public|tcp|false|true|true|Web Interface||tasks" diff --git a/containers/vikunja/vikunja.svg b/containers/vikunja/vikunja.svg new file mode 100644 index 0000000..ffbe519 --- /dev/null +++ b/containers/vikunja/vikunja.svg @@ -0,0 +1,9 @@ + + + + + + + + diff --git a/scripts/source/files/arrays/function_manifest.sh b/scripts/source/files/arrays/function_manifest.sh index 1e59121..1ac9cd8 100644 --- a/scripts/source/files/arrays/function_manifest.sh +++ b/scripts/source/files/arrays/function_manifest.sh @@ -959,12 +959,14 @@ declare -gA LP_FN_MAP=( [updaterTagExists]="cli/commands/updater/cli_updater_ladder.sh" [updaterTagGreater]="webui/data/generators/updater/webui_updater_scan.sh" [updaterTagIncrement]="cli/commands/updater/cli_updater_ladder.sh" + [updaterTagLastUpdated]="webui/data/generators/updater/webui_updater_scan.sh" [updaterTagNums]="webui/data/generators/updater/webui_updater_scan.sh" [updaterTagOf]="webui/data/generators/updater/webui_updater_scan.sh" [updaterTagShape]="webui/data/generators/updater/webui_updater_scan.sh" [updaterTagSortKey]="cli/commands/updater/cli_updater_ladder.sh" [updaterUpgradeApp]="cli/commands/updater/cli_updater_upgrade.sh" [_updaterUpgradeGenDir]="cli/commands/updater/cli_updater_upgrade.sh" + [_updaterUpgradePruneImages]="cli/commands/updater/cli_updater_upgrade.sh" [_updaterUpgradeRollbackStep]="cli/commands/updater/cli_updater_upgrade.sh" [updaterVerifyGeneric]="cli/commands/updater/cli_updater_verify.sh" [updaterVerifyUpgrade]="cli/commands/updater/cli_updater_verify.sh" @@ -2005,12 +2007,14 @@ declare -gA LP_FN_ROOT=( [updaterTagExists]="scripts" [updaterTagGreater]="scripts" [updaterTagIncrement]="scripts" + [updaterTagLastUpdated]="scripts" [updaterTagNums]="scripts" [updaterTagOf]="scripts" [updaterTagShape]="scripts" [updaterTagSortKey]="scripts" [updaterUpgradeApp]="scripts" [_updaterUpgradeGenDir]="scripts" + [_updaterUpgradePruneImages]="scripts" [_updaterUpgradeRollbackStep]="scripts" [updaterVerifyGeneric]="scripts" [updaterVerifyUpgrade]="scripts" @@ -3085,12 +3089,14 @@ updaterSetAnchorVersion() { unset -f updaterSetAnchorVersion; __lpAutoload "${in updaterTagExists() { unset -f updaterTagExists; __lpAutoload "${install_scripts_dir}cli/commands/updater/cli_updater_ladder.sh"; updaterTagExists "$@"; } updaterTagGreater() { unset -f updaterTagGreater; __lpAutoload "${install_scripts_dir}webui/data/generators/updater/webui_updater_scan.sh"; updaterTagGreater "$@"; } updaterTagIncrement() { unset -f updaterTagIncrement; __lpAutoload "${install_scripts_dir}cli/commands/updater/cli_updater_ladder.sh"; updaterTagIncrement "$@"; } +updaterTagLastUpdated() { unset -f updaterTagLastUpdated; __lpAutoload "${install_scripts_dir}webui/data/generators/updater/webui_updater_scan.sh"; updaterTagLastUpdated "$@"; } updaterTagNums() { unset -f updaterTagNums; __lpAutoload "${install_scripts_dir}webui/data/generators/updater/webui_updater_scan.sh"; updaterTagNums "$@"; } updaterTagOf() { unset -f updaterTagOf; __lpAutoload "${install_scripts_dir}webui/data/generators/updater/webui_updater_scan.sh"; updaterTagOf "$@"; } updaterTagShape() { unset -f updaterTagShape; __lpAutoload "${install_scripts_dir}webui/data/generators/updater/webui_updater_scan.sh"; updaterTagShape "$@"; } updaterTagSortKey() { unset -f updaterTagSortKey; __lpAutoload "${install_scripts_dir}cli/commands/updater/cli_updater_ladder.sh"; updaterTagSortKey "$@"; } updaterUpgradeApp() { unset -f updaterUpgradeApp; __lpAutoload "${install_scripts_dir}cli/commands/updater/cli_updater_upgrade.sh"; updaterUpgradeApp "$@"; } _updaterUpgradeGenDir() { unset -f _updaterUpgradeGenDir; __lpAutoload "${install_scripts_dir}cli/commands/updater/cli_updater_upgrade.sh"; _updaterUpgradeGenDir "$@"; } +_updaterUpgradePruneImages() { unset -f _updaterUpgradePruneImages; __lpAutoload "${install_scripts_dir}cli/commands/updater/cli_updater_upgrade.sh"; _updaterUpgradePruneImages "$@"; } _updaterUpgradeRollbackStep() { unset -f _updaterUpgradeRollbackStep; __lpAutoload "${install_scripts_dir}cli/commands/updater/cli_updater_upgrade.sh"; _updaterUpgradeRollbackStep "$@"; } updaterVerifyGeneric() { unset -f updaterVerifyGeneric; __lpAutoload "${install_scripts_dir}cli/commands/updater/cli_updater_verify.sh"; updaterVerifyGeneric "$@"; } updaterVerifyUpgrade() { unset -f updaterVerifyUpgrade; __lpAutoload "${install_scripts_dir}cli/commands/updater/cli_updater_verify.sh"; updaterVerifyUpgrade "$@"; }