Files

429 lines
15 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-umami",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "Umami"
},
"tagline": {
"en_US": "Privacy-focused, self-hosted web analytics."
},
"description": {
"en_US": "Umami is a privacy-focused web analytics platform. This recipe uses the official Umami image with a separate PostgreSQL LXC for persistent analytics data."
},
"category": "monitoring",
"category_label": "Monitoring & Analytics",
"author": "Umami Software",
"developer": "Umami Software",
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/umami.webp",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "http",
"port": 3000,
"path": "/"
},
"website": "https://umami.is/",
"documentation": "https://docs.umami.is/docs/install",
"repository": "https://github.com/umami-software/umami",
"tips": [
"The initial administrator login is admin / umami. Change the password immediately after the first sign-in.",
"Umami runs in one LXC and PostgreSQL in a separate private LXC. The PostgreSQL managed volume stores analytics data; the Umami service has no data volume.",
"The official Compose healthcheck probes /api/heartbeat. ProxMenux performs its standard first-start HTTP check against the web root; verify /api/heartbeat and sign-in separately during runtime validation.",
"The Compose file uses official Umami and PostgreSQL images. ProxMenux generates a unique database password, APP_SECRET, and 64-character TWO_FACTOR_ENCRYPTION_KEY."
],
"mini_changelog": [],
"display_version": null,
"updated_at": "2026-10-23"
},
"source": {
"provider": "umami",
"repository": "https://github.com/umami-software/umami",
"default_branch": "master",
"revision": "559e3c607c23d2c72d9bd4f6481bda428255323c",
"image_repository_url": "https://github.com/umami-software/umami/pkgs/container/umami",
"readme_pushed_at": "",
"compose_sha256": "fb542a641c14fc2b1ff0d59558a197ed4f607b6608bf812afd20dad662ae0e8c",
"generated_at": "2026-10-27T09:38:05+00:00",
"readme_raw_url": "https://raw.githubusercontent.com/umami-software/umami/559e3c607c23d2c72d9bd4f6481bda428255323c/docker-compose.yml"
},
"container_contract": {
"service_name": "umami",
"container_name": "umami",
"image": {
"reference": "ghcr.io/umami-software/umami:latest",
"registry": "ghcr.io",
"repository": "ghcr.io/umami-software/umami",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-selected-tag-to-architecture-digest-at-install"
},
"environment": [
{
"name": "DATABASE_URL",
"example": "postgresql://umami:${GENERATED_DB_PASSWORD}@db:5432/umami",
"required": true,
"sensitive": true,
"source": "official-docker-compose"
},
{
"name": "APP_SECRET",
"example": "${GENERATED_APP_SECRET}",
"required": true,
"sensitive": true,
"source": "official-documentation"
},
{
"name": "TWO_FACTOR_ENCRYPTION_KEY",
"example": "${GENERATED_TWO_FACTOR_ENCRYPTION_KEY}",
"required": true,
"sensitive": true,
"source": "official-docker-compose"
}
],
"volumes": [],
"ports": [
{
"container_port": 3000,
"published_example": 3000,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [
{
"name": "db",
"image": "postgres:15-alpine"
}
],
"restart": "always",
"stop_grace_period": null,
"original_compose": "---\nservices:\n umami:\n image: ghcr.io/umami-software/umami:latest\n ports:\n - \"3000:3000\"\n environment:\n DATABASE_URL: postgresql://umami:umami@db:5432/umami\n APP_SECRET: replace-me-with-a-random-string\n # Required for two-factor authentication, generate with: openssl rand -hex 32\n TWO_FACTOR_ENCRYPTION_KEY: replace-me-with-a-64-character-hex-string\n depends_on:\n db:\n condition: service_healthy\n init: true\n restart: always\n healthcheck:\n test: [\"CMD-SHELL\", \"curl http://localhost:3000/api/heartbeat\"]\n interval: 5s\n timeout: 5s\n retries: 5\n db:\n image: postgres:15-alpine\n environment:\n POSTGRES_DB: umami\n POSTGRES_USER: umami\n POSTGRES_PASSWORD: umami\n volumes:\n - umami-db-data:/var/lib/postgresql/data\n restart: always\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}\"]\n interval: 5s\n timeout: 5s\n retries: 5\nvolumes:\n umami-db-data:\n"
},
"compose_stack": {
"project_name": "umami",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "umami",
"service_count": 2,
"services": [
{
"name": "db",
"image": "postgres:15-alpine",
"is_main": false,
"role": "dependency",
"vmid_offset": 1,
"depends_on": [],
"frontend_network": false,
"private_network": true,
"compose": {
"image": "postgres:15-alpine",
"environment": {
"POSTGRES_DB": "umami",
"POSTGRES_USER": "umami",
"POSTGRES_PASSWORD": "${GENERATED_DB_PASSWORD}"
},
"volumes": [
"umami-db-data:/var/lib/postgresql/data"
],
"restart": "always",
"healthcheck": {
"test": [
"CMD-SHELL",
"pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"
],
"interval": "5s",
"timeout": "5s",
"retries": 5
}
}
},
{
"name": "umami",
"image": "ghcr.io/umami-software/umami:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [
"db"
],
"frontend_network": true,
"private_network": true,
"compose": {
"image": "ghcr.io/umami-software/umami:latest",
"ports": [
"3000:3000"
],
"environment": {
"DATABASE_URL": "postgresql://umami:${GENERATED_DB_PASSWORD}@db:5432/umami",
"APP_SECRET": "${GENERATED_APP_SECRET}",
"TWO_FACTOR_ENCRYPTION_KEY": "${GENERATED_TWO_FACTOR_ENCRYPTION_KEY}"
},
"depends_on": {
"db": {
"condition": "service_healthy"
}
},
"init": true,
"restart": "always",
"healthcheck": {
"test": [
"CMD-SHELL",
"curl http://localhost:3000/api/heartbeat"
],
"interval": "5s",
"timeout": "5s",
"retries": 5
}
}
}
],
"top_level": {
"name": "umami",
"volumes": {
"umami-db-data": {}
}
},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": true,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-replace-compose-service-dns",
"dependency_external_access": "disabled",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "umami-database-data",
"service": "db",
"container_path": "/var/lib/postgresql/data",
"mode": "managed-volume",
"user_selectable": true,
"backup": true,
"shared_with_other_lxc": false,
"default": "managed-volume",
"installation_choice": [
"managed-volume",
"host-bind"
]
}
],
"orchestration": {
"reserve_vmids_atomically": 2,
"start_order": [
"db",
"umami"
],
"stop_order": [
"umami",
"db"
],
"dependency_readiness": "postgres-healthcheck-before-application",
"rollback_on_failure": "preserve-created-containers-and-volumes-for-diagnosis"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": [
{
"id": "db-password",
"strategy": "generate-cryptographically-random-at-install",
"bindings": [
{
"service": "db",
"environment_variable": "POSTGRES_PASSWORD"
},
{
"service": "umami",
"environment_variable": "DATABASE_URL"
}
]
},
{
"id": "app-secret",
"strategy": "generate-cryptographically-random-at-install",
"bindings": [
{
"service": "umami",
"environment_variable": "APP_SECRET"
}
]
},
{
"id": "two-factor-encryption-key",
"strategy": "generate-cryptographically-random-at-install",
"bindings": [
{
"service": "umami",
"environment_variable": "TWO_FACTOR_ENCRYPTION_KEY"
}
]
}
]
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "http",
"port": 3000,
"path": "/",
"source": "official-docker-compose"
}
],
"credentials": [
{
"label": "Initial Umami administrator",
"type": "static-default",
"username": "admin",
"password": "umami",
"change_required": true,
"source": "official-documentation",
"retrieval": null
}
]
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-zfs",
"volume_storage": "local-zfs",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 60
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"adaptations": [
{
"id": "compose-dependency-network",
"upstream_behavior": "Docker Compose resolves the db service name on the project network and waits until PostgreSQL is healthy.",
"native_lxc_behavior": "ProxMenux creates a private Proxmox bridge, gives each service its own LXC, maps the db alias, and waits for PostgreSQL readiness before first starting Umami.",
"reason": "The two official Compose services run in separate native OCI LXCs.",
"behavioral_impact": "PostgreSQL stays on the private service network and has no published port.",
"validation": "passed"
},
{
"id": "generated-compose-secrets",
"upstream_behavior": "The official Compose file uses example values for APP_SECRET, TWO_FACTOR_ENCRYPTION_KEY, and PostgreSQL credentials.",
"native_lxc_behavior": "ProxMenux generates a unique PostgreSQL password, APP_SECRET, and a 64-character hexadecimal two-factor key for each installation.",
"reason": "Do not reuse example credentials between installations.",
"behavioral_impact": "The administrator still changes Umami’s documented initial admin password after first sign-in.",
"validation": "passed"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "The official Compose file probes /api/heartbeat every five seconds for Umami and uses pg_isready for PostgreSQL.",
"native_lxc_behavior": "The stack waits for PostgreSQL readiness, then ProxMenux performs its standard first-start HTTP check at the Umami web root. It does not install a continuous health monitor.",
"reason": "The current generic installer uses the application endpoint for its first-start check.",
"behavioral_impact": "Runtime validation should separately check /api/heartbeat and the interactive login.",
"validation": "passed"
}
],
"installer_profile": {
"stack_driver": "generic-multi-lxc-stack"
},
"security_profile": {
"requires_privileged_lxc": false,
"source_requests_privileged_lxc": false,
"optional_privileged_lxc": false,
"requires_host_pid_namespace": false,
"source_requests_relaxed_confinement": false,
"requires_relaxed_confinement": false,
"optional_relaxed_confinement": false,
"risk_level": "normal",
"confirmation_required": false,
"warning": "The official Umami and PostgreSQL Compose services do not request privileged mode or relaxed host confinement."
}
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"depends_on",
"environment",
"healthcheck",
"image",
"init",
"ports",
"restart",
"volumes"
],
"untranslated_blockers": [],
"policy": "The official two-service Compose model is represented as two native OCI LXCs with a private PostgreSQL dependency and managed database storage. ProxMenux applies a first-start web-root check; validate the official heartbeat endpoint and login separately."
},
"validation": {
"schema": "passed",
"clean_install": "passed",
"service_health": "passed",
"restart_persistence": "passed",
"backup_restore": "pending",
"update_preserves_data": "pending",
"remove": "passed",
"advanced_configuration": "pending",
"storage_modes": "pending",
"modify": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false,
"dependency_lifecycle": {
"implementation": "proxmox-hookscript",
"trigger": "main-lxc-pre-start",
"waits_for_dependency_healthchecks": true,
"stops_dependencies_with_main": false
}
}
}