job "vaultwarden" { datacenters = ["dc1"] type = "service" constraint { attribute = "${attr.kernel.name}" value = "linux" } constraint { attribute = "${attr.cpu.arch}" operator = "regexp" value = "arm64" } group "vaultwarden" { count = 1 task "vaultwarden" { driver = "docker" config { # image = "vaultwarden/server:latest" image = "vaultwarden/server:1.32.7" memory_hard_limit = 2048 ports = ["http"] volumes = [ "/mnt/configs/${NOMAD_GROUP_NAME}/data:/data", ] } env { // vaultwarden_SCAN_INTERVAL = "120" // vaultwarden_MUSIC_PATH = "/music" // vaultwarden_PODCAST_PATH = "/podcasts" ADMIN_TOKEN = "VReYRX0RuSw3mxmGFG4+2ECY71l/wYmuD52NOWDur6e43z/inbUmJGUr5KU4wtjW" ENABLE_DB_WAL = "false" DATABASE_URL= "postgresql://postgres:postgres@master.postgres.service.dc1.consul:5432/vaultwarden" } resources { cpu = 100 # 100 MHz memory = 128 # 128 MB } service { name = "vaultwarden" tags = [ "vaultwarden", "web", "urlprefix-/vaultwarden", "backend", "traefik.http.routers.vaultwardenlan.rule=Host(`vaultwarden.service.dc1.consul`)", "traefik.http.routers.vaultwardenwan.rule=Host(`vault.fbleagh.duckdns.org`)", "traefik.http.routers.vaultwardenwan-admin.rule=(Host(`vault.fbleagh.duckdns.org`) && PathPrefix(`/admin/`))", "traefik.http.routers.vaultwardenwan.tls=true", // "traefik.http.routers.vaultwardenwan.tls.certresolver=myresolver-int", "traefik.http.middlewares.vaultwardenwan-admin-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.4.0/22", "enable_gocast", "gocast_vip=192.168.1.246/32", "gocast_nat=tcp:8081:8081", "gocast_nat=udp:8081:8081" ] // "traefik.http.middlewares.vaultwarden_auth.basicauth.users=admin:$2y$05$cJGONoS0BFTeBUXqmETikeI14QhLDKIDkYuPdA1umIOC129grVMAm", // https://github.com/dani-garcia/vaultwarden/issues/676 // labels: // - traefik.enable=true // - traefik.docker.network=traefik // # Define middleware of 'redirect-https', set scheme and set permanent redirect as true // - traefik.http.middlewares.redirect-https.redirectScheme.scheme=https // - traefik.http.middlewares.redirect-https.redirectScheme.permanent=true // # Define service of 'bitwarden' for UI port when using entrypoint websecure (port 443) // - traefik.http.services.bitwarden.loadbalancer.server.port=80 // - traefik.http.routers.bitwarden-https.rule=Host(`bitwarden.domain.tld`) // - traefik.http.routers.bitwarden-https.entrypoints=websecure // - traefik.http.routers.bitwarden-https.service=bitwarden // # Define service of 'bitwarden' for UI port when using entrypoint web (port 80) // - traefik.http.routers.bitwarden-http.rule=Host(`bitwarden.domain.tld`) // - traefik.http.routers.bitwarden-http.entrypoints=web // - traefik.http.routers.bitwarden-http.middlewares=redirect-https // - traefik.http.routers.bitwarden-http.service=bitwarden // # Define service of 'bitwarden-websocket' for socket port when using entrypoint websecure (port 443) // - traefik.http.services.bitwarden-websocket.loadbalancer.server.port=3012 // - traefik.http.routers.bitwarden-websocket-https.rule=Host(`bitwarden.domain.tld`) && Path(`/notifications/hub`) // - traefik.http.routers.bitwarden-websocket-https.entrypoints=websecure // - traefik.http.routers.bitwarden-websocket-https.service=bitwarden-websocket // # Define service of 'bitwarden-websocket' for socket port when using entrypoint web (port 80) // - traefik.http.routers.bitwarden-websocket-http.rule=Host(`bitwarden.domain.tld`) && Path(`/notifications/hub`) // - traefik.http.routers.bitwarden-websocket-http.entrypoints=web // - traefik.http.routers.bitwarden-websocket-http.middlewares=redirect-https // - traefik.http.routers.bitwarden-websocket-http.service=bitwarden-websocket port = "http" meta { ALLOC = "${NOMAD_ALLOC_ID}" } check { type = "tcp" interval = "10s" timeout = "2s" } } } #end vaultwarden task "init" { driver = "docker" lifecycle { hook = "prestart" sidecar = false } config { image = "ghcr.io/sstent/rsync" memory_hard_limit = 2048 volumes = [ "/mnt/configs/${NOMAD_GROUP_NAME}/data:/config", "/mnt/Public/config/${NOMAD_GROUP_NAME}:/configbackup", "/mnt/Public/config/locks:/locks", ] args = ["flock", "-x", "/locks/${NOMAD_GROUP_NAME}_rsync.lock", "rsync", "-avz", "--exclude='logs'", "--exclude='/run/*.sock'", "/configbackup/", "/config/", "--delete-before"] } resources { cpu = 20 # 500 MHz memory = 20 # 128MB } } #end init task task "finalsync" { driver = "docker" lifecycle { hook = "poststop" } config { // image = "pebalk/rsync" image = "ghcr.io/sstent/rsync" memory_hard_limit = 2048 volumes = [ "/mnt/configs/${NOMAD_GROUP_NAME}/data:/config", "/mnt/Public/config/${NOMAD_GROUP_NAME}:/configbackup", "/mnt/Public/config/locks:/locks", ] args = ["flock", "-x", "/locks/${NOMAD_GROUP_NAME}_rsync.lock", "rsync", "-av", "--exclude='logs'", "--exclude='/run/*.sock'", "/config/", "/configbackup/", "--remove-source-files"] } resources { cpu = 20 # 500 MHz memory = 20 # 128MB } } #end finalsync task task "sync" { driver = "docker" lifecycle { hook = "poststart" sidecar = true } config { memory_hard_limit = "2048" image = "ghcr.io/sstent/rsync" volumes = [ "/mnt/configs/${NOMAD_GROUP_NAME}/data:/config", "/mnt/Public/config/${NOMAD_GROUP_NAME}:/configbackup", ] args = ["client"] } env { CRON_TASK_1 = "50 * * * * rsync -av --exclude='*.db' --exclude='*.db' --exclude='.*.db-litestream' --exclude='generations' /config/ /configbackup/;" } resources { cpu = 20 # 500 MHz memory = 20 # 128MB } } network { // mbits = 100 port "http" { static = 8081 to = 80 } } } } // Restore // There is no automated restore process to prevent accidential data loss. So if you need to restore a backup you need to do this manually by following the steps below (assuming your backups are located at ./backup/ and your vaultwarden data ist located at /var/lib/docker/volumes/vaultwarden/_data/) // # Delete any existing sqlite3 files // rm /var/lib/docker/volumes/vaultwarden/_data/db.sqlite3* // # Copy the database to the vaultwarden folder // cp ./backup/db.sqlite3 /var/lib/docker/volumes/vaultwarden/_data/db.sqlite3 // # Extract the additional folder from the archive // tar -xzvf ./backup/data.tar.gz -C /var/lib/docker/volumes/vaultwarden/_data/ // ENV Description // BACKUP_ADD_DATABASE 1 Set to true to include the database itself in the backup // BACKUP_ADD_ATTACHMENTS 1 Set to true to include the attachments folder in the backup // BACKUP_ADD_CONFIG_JSON 1 Set to true to include config.json in the backup // BACKUP_ADD_ICON_CACHE 1 Set to true to include the icon cache folder in the backup // BACKUP_ADD_RSA_KEY 1 Set to true to include the RSA keys in the backup // BACKUP_ADD_SENDS 1 Set to true to include the sends folder in the backup // BACKUP_DIR Seths the path of the backup folder inside the container // BACKUP_DIR_PERMISSIONS Sets the permissions of the backup folder (CAUTION 2). Set to -1 to disable. // CRONFILE Path to the cron file inside the container // CRON_TIME Cronjob format "Minute Hour Day_of_month Month_of_year Day_of_week Year" // DELETE_AFTER Delete old backups after X many days. Set to 0 to disable // TIMESTAMP Set to true to append timestamp to the backup file // GID Group ID to run the cron job with // HEALTHCHECK_URL Set a healthcheck url like https://hc-ping.com/xyz // LOG_LEVEL DEBUG, INFO, WARNING, ERROR, CRITICAL are supported // LOG_DIR Path to the logfile folder inside the container // LOG_DIR_PERMISSIONS Sets the permissions of the backup folder. Set to -1 to disable. // TZ Set the timezone inside the container 3 // UID User ID to run the cron job with // VW_DATA_FOLDER 4 Set the location of the vaultwarden data folder inside the container // VW_DATABASE_URL 4 Set the location of the vaultwarden database file inside the container // VW_ATTACHMENTS_FOLDER 4 Set the location of the vaultwarden attachments folder inside the container // VW_ICON_CACHE_FOLDER 4 Set the location of the vaultwarden icon cache folder inside the container