job "bookstack" { datacenters = ["dc1"] region = "global" group "bookstack" { count = 1 network { mode = "bridge" } volume "data" { source = "bookstack-data" type = "csi" access_mode = "multi-node-multi-writer" attachment_mode = "file-system" } service { name = "bookstack" port = 8080 connect { sidecar_service { proxy { upstreams { destination_name = "mariadb" local_bind_port = 3306 # Work arround, see https://github.com/hashicorp/nomad/issues/18538 destination_type = "service" } upstreams { destination_name = "smtp" local_bind_port = 25 # Work arround, see https://github.com/hashicorp/nomad/issues/18538 destination_type = "service" } } } sidecar_task { config { args = [ "-c", "${NOMAD_SECRETS_DIR}/envoy_bootstrap.json", "-l", "${meta.connect.log_level}", "--concurrency", "${meta.connect.proxy_concurrency}", "--disable-hot-restart" ] } resources { cpu = 50 memory = 64 } } } tags = [ "traefik.enable=true", "traefik.http.routers.bookstack.entrypoints=https", "traefik.http.routers.bookstack.rule=Host(`bookstack.example.org`)", "traefik.http.middlewares.csp-bookstack.headers.contentsecuritypolicy=default-src 'self';font-src 'self' data:;img-src 'self' data:;script-src 'self' 'unsafe-inline' 'unsafe-eval';style-src 'self' 'unsafe-inline';", "traefik.http.routers.bookstack.middlewares=security-headers@file,rate-limit-std@file,forward-proto@file,inflight-std@file,hsts@file,compression@file,csp-bookstack", ] } task "bookstack" { driver = "docker" config { image = "danielberteaud/bookstack:24.02.2-1" pids_limit = 100 readonly_rootfs = true volumes = ["secrets/bookstack.env:/app/.env"] mount { type = "tmpfs" target = "/tmp" tmpfs_options { size = 5000000 } } } env { } vault { policies = ["bookstack"] env = false disable_file = true change_mode = "noop" } # Use a template block instead of env {} so we can fetch values from vault template { data = <<_EOT LANG=fr_FR.utf8 TZ=Europe/Paris WAIT_FOR_TARGETS=127.0.0.1:3306 _EOT destination = "secrets/.env" perms = 400 env = true } # Ensure only the first allocation runs the database initialization / upgrades template { data = <<_EOT {{- if eq (env "NOMAD_ALLOC_INDEX") "0" }} BOOKSTACK_INIT_DB=true {{- else }} MINIT_DISABLE=bookstack-queue BOOKSTACK_INIT_DB=false {{- end }} _EOT destination = "secrets/bookstack_initdb.env" env = true } # BookStack won't work with env vars because PHP clears env # So, publish BookStack settings here template { data = <<_EOT APP_KEY={{ with secret "kv/service/bookstack" }}{{ .Data.data.app_key }}{{ end }} APP_LANG=fr APP_PROXIES=127.0.0.1 APP_URL=https://bookstack.example.org CACHE_DRIVER=database CACHE_PREFIX=bookstack DB_DATABASE=bookstack DB_HOST=127.0.0.1 DB_PASSWORD={{ with secret "database/creds/bookstack" }}{{ .Data.password }}{{ end }} DB_PORT=3306 DB_USERNAME={{ with secret "database/creds/bookstack" }}{{ .Data.username }}{{ end }} DISABLE_EXTERNAL_SERVICES=true MAIL_DRIVER=smtp MAIL_FROM=no-reply@bookstack.example.org MAIL_FROM_NAME=bookstack MAIL_HOST=127.0.0.1 MAIL_PORT=25 QUEUE_CONNECTION=database SESSION_COOKIE_NAME=bookstack_session SESSION_DRIVER=database SESSION_LIFETIME=240 STORAGE_TYPE=local_secure_restricted WKHTMLTOPDF=/usr/local/bin/wkhtmltopdf _EOT destination = "secrets/bookstack.env" uid = 100100 gid = 100000 perms = 400 } volume_mount { volume = "data" destination = "/data" } resources { cpu = 100 memory = 256 memory_max = 512 } } } }