Compare commits

...

16 commits

Author SHA1 Message Date
412054e3cd
restic: Fix extensions to yaml 2025-07-18 21:37:12 +02:00
945868feff
vault: Add restic secrets 2025-07-18 21:37:11 +02:00
64b85c0c40
arr: Add restic backup 2025-07-18 21:37:10 +02:00
363ce9ae6f
arr: Remove leftover arr.yml file 2025-07-18 21:37:10 +02:00
1fd72a05a6
restic: Fix backup container local repo mounting
If our chosen backup repo is a local one, each restic container needs to
mount the local path as a volume, otherwise the data is stuck in the
container itself.
2025-07-18 21:37:09 +02:00
f1be696479
grocy: Add docker hostname to backup container 2025-07-18 21:37:08 +02:00
9cf1a5e571
grocy: Add restic backup 2025-07-18 21:37:08 +02:00
af5b647daf
grocy: Fix container service name 2025-07-18 21:37:07 +02:00
cd842ea4b5
Add hostname to restic containers
Will pass through the hostname to any snapshots set up.
The hostname is _not_ derived from the random docker container string
but instead takes the name of the _host_ on which docker is running
(from ansible facts).

The hostname in combination with the tag should point to the correct
host -> stack which is being backed up.
2025-07-18 21:37:07 +02:00
b81328d400
paperless: Add restic backups 2025-07-18 21:37:06 +02:00
e13d85990c
restic: Fix template env vars 2025-07-18 21:37:06 +02:00
065fd4562b
vault: Add restic notification secrets 2025-07-18 21:37:05 +02:00
fab6f5ff7c
restic: Add notification
Notifies double for each prune/check run which may need to be fixed.
Also custom notification contents cannot currently be passed.

Lastly, we should put identifying information into the notification body
(such as the hostname/container name for which the notification is
relevant).
2025-07-18 21:37:05 +02:00
003cf64a77
restic: Update docs 2025-07-18 21:37:04 +02:00
86d49a756b
restic: Add stack
Adapted from cloudserve-infrastructure, implements a backup stack using
restic. The actual backups have to be implemented by individual other
roles but this sets up initialization, pruning and checking of a repository.
2025-07-18 21:37:03 +02:00
93876315ca
repo: Rename all yml extensions to yaml 2025-07-18 21:37:03 +02:00
28 changed files with 345 additions and 207 deletions

View file

@ -1,33 +1,46 @@
$ANSIBLE_VAULT;1.1;AES256
61653738666234666537383737636631323931396632353236366639323833363134313066613962
3730306266353834303135653939323561666131333539380a333039663466393061343736653935
38613532346132303730363835373165326361373561666565316332623964316265306131663332
3832373861666138330a646631346262666233383938366234373335383064353662326461656430
35626334356566613731333639663130306133353439666234636137636265313662393730626232
37633430663438666461353735656461623165316134346130663963356464656436313966613739
35373763633936336565666261353631366531323430663461376338373265393235313932363733
66323634656539303732303338376264353935316538373465633462386466383662626534623365
38363362653535386130366462393365393731313034316431373039393331396231663365616435
31373632633264383266623733613530333134643730396336373461633739383436623736613638
39303163373234313534323562643836636337323266366538323932656563376163376162306165
31356165343739373237363734393230356236363339653564326537313336663036313437646636
35313336396361353365323763643861656561633235383732376236333232363565376365386232
32353737373239396436316538323661303164373765343936643736663035323237663935643834
39333238666162363366633938333231313966613430303236636634316136373433323536613833
61386434636464633662383736323630326630313561356335306663333864643462366335643430
34396331633935656632323062613433386234386535613337313561353037356633376664333634
62303063636135343737323331623736303636643735613337633530666134333266323934376631
62386535323834323435373362333662613637383065346335373465343765663836626434666463
39623162313438346239393261613738376435636539623663646461396330326661343633353531
66643362326464376437643732366466633332323837323433343165313735653331346431656136
32376165666437373435646566373036313639316165353639626435333330626530373662333031
37656463333231356465383039336237626235613331376639656665303431353131336436653839
32383031376134643236333231323863633933376238613462623034663262316339353061343635
36336338323331343866643836666530616639313933306536343631303635383862363633373562
65663930306461316363376364663935663566393335396130626436316262643730393133363837
63343334613966343466646366303137663965633639653262316630626436346461643533393135
31303630616662623237313331356263613535323739616162393165336163346161303836653638
30386636663230613731383165333462363033333734326662373961383236386631643139373934
38353732393265656162633739623061333833353138303664633463643234396338643736353132
32313763656165643963373236346364636534333964383131373839616435356631386463646437
39336237356337383930
66623361613033616239323361396635633932346566663666346466613132303332663465383037
3334373161356131653039326630666238303863663034360a633865303562663162303530656436
36346162613333346133363533343731313965663731336130643333633832663161653437393663
3936643262306639370a323431343661316564393165386634666635633337356134373862326431
34633134643062643837316133616138623736306330316538623632633038393038316365316433
30383363356633613833373738653338376335306361636265303232353838393866353830363434
37353263353734623161333334316433303061643162363033333466326236373761366636343437
35343765303462303231373531616362656634313837383631346263333962366634306530353036
65363033346661323766613961343832323536313339306331626338643336643433333039633666
63336633386531633632346337393435613338306338363636316138353233366334326435396466
37363162636539313831323038383535613062373034346437623337393764663133623436356462
33626361343136376136623964363638303138323330306366353963623962313936666261323334
61393665313164646165316666333663613163386631643262663233666636386566363565626430
35633664643438316263663035326636313532333735396537646266373539373063396532323532
63653262333430663065653838336636616137346538393431306531323234376631616331613437
65346332383438336137363965643438306564656538316331643566303932353336303931333936
31306362343464316263316638613831626539323033313031656462373936303534366438383632
33376562643836303466663437353731343833636630303636376266393866616532636537326130
32633964396132656135376262316563396338336132313436313533616237656335386162363837
61666134613830346361666266633538653861326263666565363738383032656536383637666363
66323135336261376330346633373538383338613765356238323666333266333365646365343563
33363162633333353234353838623864653862383431396237623065303232343034333735333064
34636261333465666433363764373934313139306631616234626365306531303232336163363466
36646666336466663034386634616564626366653963623436343630343263306164313231326166
31326235346363373664353665666436653532333864303864336535653365623465333764653465
66303037303839336164373062613836653732393964323634306438656531613364396132353965
38353766386461663161636139326361663461346262626564326335626339346635356139336238
64373161346363653661666661323732643236303561356164396136343235613762336264366136
65333938633433303365646665346263636262303062626634336564616164626563353665396331
32636164393863336237336331343836373564313935393661646538656539326333656439623363
30653538346661383061363263326430323730636234346365653835346466666439393466303033
64343133326664356432326631363234356235313035613134306436613364633836633032326332
61323861386333653130386637323034336262396433653730323863353230393461316663613339
37333334336630653037333366666561363332343533323966346536363237373337346439656533
30633239346463373734666330303934316438663666366435613362336661623530333034616165
33363336323539383565396337663232393835383734613064393331666135366266633861366333
63653466356361343732303864373535366433313130303230323334376561363539336638363930
61353666393366306636333437313736386165303535353534326433326136396637613236626634
66376239376639393662616161623461643634633930633364333130366136343066376132633934
66346165353837613837306231383361326236373132353239356164626264366437316639616263
31623066356231323138303339356138303939343631636337353137663137356562353333376636
38313066313431386633316339303835363135633434343663636338636365306430643436383430
66623666663063353439303433386538623762626563323863396335336461646130353466626230
62393063393936393661636235663730623834626432363563353536353339643135336464323936
3733

View file

@ -54,3 +54,8 @@
ansible.builtin.import_role:
name: grocy
tags: grocy
- name: Set up Restic stack
ansible.builtin.import_role:
name: restic
tags: restic

View file

@ -20,6 +20,9 @@ arrstack_puid: "{{ puid | default(1000) }}"
arrstack_pgid: "{{ pgid | default(100) }}"
arrstack_umask_set: "{{ umask_set | default('022') }}"
arrstack_restic_enable: true
arrstack_restic_cron: 0 30 2 * * *
arrstack_env_dir: /opt/arrstack
arrstack_serve_dir: /srv
arrstack_serve_dir_create: true

View file

@ -1,171 +0,0 @@
services:
sonarr:
container_name: sonarr
image: lscr.io/linuxserver/sonarr:latest
ports:
- 8989:8989
environment:
- PUID=${PUID}
- PGID=${PGID}
- UMASK_SET=022
- TZ=${TZ}
volumes:
- "./config/sonarr:/config"
- "CHANGE_TO_COMPOSE_DATA_PATH:/data"
restart: unless-stopped
radarr:
container_name: radarr
image: lscr.io/linuxserver/radarr:latest
ports:
- 7878:7878
environment:
- PUID=${PUID}
- PGID=${PGID}
- UMASK_SET=022
- TZ=${TZ}
volumes:
- "./config/radarr:/config"
- "CHANGE_TO_COMPOSE_DATA_PATH:/data"
restart: unless-stopped
lidarr:
container_name: lidarr
image: lscr.io/linuxserver/lidarr:latest
ports:
- 8686:8686
environment:
- PUID=${PUID}
- PGID=${PGID}
- UMASK_SET=022
- TZ=${TZ}
- DOCKER_MODS=linuxserver/mods:universal-docker
volumes:
- "./config/lidarr:/config"
- "CHANGE_TO_COMPOSE_DATA_PATH:/data"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
restart: unless-stopped
readarr:
container_name: readarr
image: lscr.io/linuxserver/readarr:develop
ports:
- 8787:8787
environment:
- PUID=${PUID}
- PGID=${PGID}
- UMASK_SET=022
- TZ=${TZ}
volumes:
- "./config/readarr:/config"
- "CHANGE_TO_COMPOSE_DATA_PATH:/data"
restart: unless-stopped
prowlarr:
container_name: prowlarr
image: lscr.io/linuxserver/prowlarr:develop
environment:
- PUID=${PUID}
- PGID=${PGID}
- UMASK_SET=022
- TZ=${TZ}
volumes:
- "./config/prowlarr:/config"
ports:
- 9696:9696
restart: unless-stopped
sabnzbd:
container_name: sabnzbd
image: lscr.io/linuxserver/sabnzbd:latest
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
volumes:
- "./config/sabnzbd:/config"
- "CHANGE_TO_COMPOSE_DATA_PATH/usenet:/data/usenet:rw"
ports:
- 8080:8080
restart: unless-stopped
pia-qbittorrent:
image: j4ym0/pia-qbittorrent
container_name: pia-qbittorrent
cap_add:
- NET_ADMIN
environment:
- UID=${PUID}
- GID=${PGID}
- TZ=${TZ}
- REGION=Netherlands
- USER=${PIA_USER}
- PASSWORD=${PIA_PASS}
volumes:
- "./config/piaqbit:/config"
- "CHANGE_TO_COMPOSE_DATA_PATH/torrent:/downloads:rw"
ports:
- "8888:8888"
restart: unless-stopped
jellyfin:
image: lscr.io/linuxserver/jellyfin:latest
container_name: jellyfin
environment:
- PUID={$PUID}
- PGID={$PGID}
- TZ=${TZ}
#- JELLYFIN_PublishedServerUrl=192.168.0.5 #optional
volumes:
- ".config/jellyfin:/config"
- "CHANGE_TO_COMPOSE_DATA_PATH/media:/data"
ports:
- 8096:8096
- 7359:7359/udp #optional - network discovery
- 1900:1900/udp #optional - dlna discovery
restart: unless-stopped
audiobookshelf:
container_name: audiobookshelf
image: ghcr.io/advplyr/audiobookshelf:latest
environment:
- PUID=${PUID}
- PGID=${PGID}
- UMASK_SET=022
- TZ=${TZ}
ports:
- 13378:80
volumes:
- "CHANGE_TO_COMPOSE_DATA_PATH/media/audio/books:/audiobooks"
- "CHANGE_TO_COMPOSE_DATA_PATH/media/audio/podcasts:/podcasts"
- ".config/audiobookshelf:/config"
- ".metadata/audiobookshelf:/metadata"
restart: unless-stopped
jellyseerr:
image: fallenbagel/jellyseerr:latest
container_name: jellyseerr
environment:
- TZ=${TZ}
ports:
- 5055:5055
volumes:
- "./config/jellyseerr:/app/config"
restart: unless-stopped
beets:
image: lscr.io/linuxserver/beets:latest
container_name: beets
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
volumes:
- "./config/beets:/config"
- "CHANGE_TO_COMPOSE_DATA_PATH/media/audio/music:/music"
- "CHANGE_TO_COMPOSE_DATA_PATH/media/audio/music-unsorted:/downloads"
- "CHANGE_TO_COMPOSE_DATA_PATH:/data"
ports:
- 8337:8337
restart: unless-stopped
homarr:
image: ghcr.io/ajnart/homarr:latest
container_name: homarr
volumes:
- /var/run/docker.sock:/var/run/docker.sock # Optional, only if you want docker integration
- ./config/homarr/configs:/app/data/configs
- ./config/homarr/icons:/app/public/icons
- ./config/homarr/data:/data
ports:
- '80:7575'
restart: unless-stopped

View file

@ -290,6 +290,26 @@ services:
caddy: "{{ arrstack_gonic_subdomain }}"
caddy.reverse_proxy: "{{ '{{' }}upstreams 80{{ '}}'}}"
{% if restic_enable is not undefined and not false and arrstack_restic_enable is not undefined and not false %}
backup:
image: mazzolino/restic
hostname: "{{ ansible_hostname }}"
environment:
TZ: "{{ restic_tz }}"
BACKUP_CRON: "{{ arrstack_restic_cron }}"
RESTIC_REPOSITORY: "{{ restic_repo }}"
RESTIC_PASSWORD: "{{ restic_pass }}"
AWS_ACCESS_KEY_ID: "{{ restic_s3_key }}"
AWS_SECRET_ACCESS_KEY: "{{ restic_s3_secret }}"
RESTIC_BACKUP_ARGS: >-
--tag arr
RESTIC_BACKUP_SOURCES: "/backup"
volumes:
{% if restic_repo is regex('^/.+') %}
- "{{ restic_repo }}:{{ restic_repo }}"
{% endif %}
- "{{ arrstack_env_dir }}:/backup/{{ arrstack_env_dir }}"
{% endif %}
networks:
caddy:

View file

@ -7,5 +7,8 @@ stack_grocy_puid: "{{ puid | default(1000) }}"
stack_grocy_pgid: "{{ pgid | default(100) }}"
stack_grocy_umask_set: "{{ umask_set | default('022') }}"
stack_grocy_restic_enable: true
stack_grocy_restic_cron: 0 15 2 * * *
stack_grocy_env_dir: /opt/stack_grocy

View file

@ -1,5 +1,5 @@
services:
sonarr:
grocy:
container_name: grocy
image: lscr.io/linuxserver/grocy:latest
networks:
@ -16,9 +16,27 @@ services:
caddy: "{{ stack_grocy_subdomain }}"
caddy.reverse_proxy: "{{ '{{' }}upstreams 80{{ '}}'}}"
{% if restic_enable is not undefined and not false and stack_grocy_restic_enable is not undefined and not false %}
backup:
image: mazzolino/restic
hostname: "{{ ansible_hostname }}"
environment:
TZ: "{{ restic_tz }}"
BACKUP_CRON: "{{ stack_grocy_restic_cron }}"
RESTIC_REPOSITORY: "{{ restic_repo }}"
RESTIC_PASSWORD: "{{ restic_pass }}"
AWS_ACCESS_KEY_ID: "{{ restic_s3_key }}"
AWS_SECRET_ACCESS_KEY: "{{ restic_s3_secret }}"
RESTIC_BACKUP_ARGS: >-
--tag grocy
RESTIC_BACKUP_SOURCES: "/backup"
volumes:
{% if restic_repo is regex('^/.+') %}
- "{{ restic_repo }}:{{ restic_repo }}"
{% endif %}
- "{{ stack_grocy_env_dir }}:/backup/{{ stack_grocy_env_dir }}"
{% endif %}
networks:
caddy:
external: true
volumes:
caddy_data: {}

View file

@ -7,6 +7,9 @@ stack_paperless_tz: "{{ timezone | default('America/Chicago') }}"
stack_paperless_puid: "{{ puid | default(1000) }}"
stack_paperless_pgid: "{{ pgid | default(100) }}"
stack_paperless_restic_enable: true
stack_paperless_restic_cron: 0 0 2 * * *
stack_paperless_env_dir: /opt/stack_paperless
stack_paperless_serve_dir: /srv
stack_paperless_serve_dir_create: true

View file

@ -65,6 +65,28 @@ services:
environment:
REDIS_ARGS: "--save 60 10"
{% if restic_enable is not undefined and not false and stack_paperless_restic_enable is not undefined and not false %}
backup:
image: mazzolino/restic
hostname: "{{ ansible_hostname }}"
environment:
TZ: "{{ restic_tz }}"
BACKUP_CRON: "{{ stack_paperless_restic_cron }}"
RESTIC_REPOSITORY: "{{ restic_repo }}"
RESTIC_PASSWORD: "{{ restic_pass }}"
AWS_ACCESS_KEY_ID: "{{ restic_s3_key }}"
AWS_SECRET_ACCESS_KEY: "{{ restic_s3_secret }}"
RESTIC_BACKUP_ARGS: >-
--tag paperless
RESTIC_BACKUP_SOURCES: "/backup"
volumes:
{% if restic_repo is regex('^/.+') %}
- "{{ restic_repo }}:{{ restic_repo }}"
{% endif %}
- "{{ stack_paperless_env_dir }}:/backup/{{ stack_paperless_env_dir }}"
- "{{ stack_paperless_serve_dir }}/documents:/backup/{{ stack_paperless_serve_dir }}/documents"
{% endif %}
networks:
caddy:
external: true

69
roles/restic/README.md Normal file
View file

@ -0,0 +1,69 @@
# restic
Backup maintenance stack.
Takes care of regularly pruning the backup repository and checking its integrity.
Supports any restic backend.
Variables set here are used in other roles to individually configure their backups.
## Defaults
```yaml
restic_tz: US/Chicago
```
The timezone to be used for any cronjobs.
Inherits from the global `timezone` variable or can be set individually.
```yaml
restic_version: latest
```
The docker image version to be used in stack creation.
```yaml
restic_repo: s3.eu-central-1.wasabisys.com/myrepo
restic_pass: <restic-pass>
```
The repository url and the restic repository password.
Can be of any type restic supports
(e.g. `/path/to/backups` for local, `s3:address.to.s3.com` for S3, etc.)
See the restic documentation for more information.
```yaml
restic_s3_key: <s3-key>
restic_s3_secret: <s3-secret>
```
The restic S3 credentials, i.e. the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.
```yaml
restic_prune_cron: 0 0 4 * * *
restic_forget_args: --prune --keep-last 14 --keep-daily 2 --keep-weekly 2
```
The default prune and forget cronjob schedule and arguments:
Prune the repository every day at 4:00 AM and keep the last 14 snapshots, 2 daily snapshots and 2 weekly snapshots.
Be aware that go-cron has an extra field in the front for seconds compared to many other implementations.
```yaml
restic_check_cron: 0 15 5 * * *
restic_check_args: --read-data-subset=5%
```
The default check cronjob schedule and arguments:
Check the repository integrity every day at 5:15 AM and in addition to structural checks,
read 5 randomly chosen % for a data integrity check.
```yaml
restic_notify_success:
restic_notify_failure:
restic_notify_exit:
```
If restic should notify the user on success/failure/exit (i.e. any outcome process finish).
Defaults to no notifications.
Uses Apprise and thus takes an [apprise URL](https://github.com/caronc/apprise/wiki) in the form of `ntfy://my-ntfy-channel`.
Setting one of these configures _both_ the prune and the check to notify the user if either is done,
so currently any success (failure/exit) notification would be doubled for each sucess (failure/exit).

View file

@ -0,0 +1,29 @@
---
# inherited from global
restic_enable: true
restic_tz: "{{ timezone | default('America/Chicago') }}"
restic_version: latest
restic_auto_init: true
restic_prune_cron: 0 0 4 * * * # go-cron starts with seconds in first pos
restic_forget_args: --prune --keep-last 14 --keep-daily 2 --keep-weekly 2
restic_check_cron: 0 30 4 * * SUN
restic_check_args: --read-data-subset=15%
# backup target
restic_repo: /opt/stack_restic_backup
restic_pass: my-restic-pass
restic_s3_key:
restic_s3_secret:
restic_notify_success:
restic_notify_failure:
restic_notify_exit:
# S3 example
# restic_repo: s3.eu-central-1.wasabisys.com/myrepo
# restic_pass: <restic-pass>
# restic_s3_key: <s3-key>
# restic_s3_secret: <s3-secret>

View file

@ -0,0 +1,7 @@
---
galaxy_info:
author: Marty Oehme
description: Installs a restic-based backup maintenance stack.
license: GPL-3.0-only
min_ansible_version: "2.9"
galaxy_tags: []

View file

@ -0,0 +1,17 @@
---
- name: Create local backup directory
ansible.builtin.file:
state: directory
path: "{{ restic_repo }}"
owner: root
group: root
mode: 0770
when: restic_repo is regex('^/.+')
- name: Deploy restic to compose
community.docker.docker_compose_v2:
project_name: restic
definition: "{{ lookup('template', 'docker-compose.yaml.j2') | from_yaml }}"
remove_orphans: true
wait: true
wait_timeout: 60

View file

@ -0,0 +1,92 @@
services:
prune:
image: "mazzolino/restic:{{ restic_version }}"
hostname: "{{ ansible_hostname }}"
networks:
- restic_notify
environment:
TZ: "{{ restic_tz }}"
SKIP_INIT: "{{ not restic_auto_init }}"
RUN_ON_STARTUP: "true"
PRUNE_CRON: "{{ restic_prune_cron }}"
RESTIC_FORGET_ARGS: "{{ restic_forget_args }}"
RESTIC_REPOSITORY: "{{ restic_repo }}"
RESTIC_PASSWORD: "{{ restic_pass }}"
AWS_ACCESS_KEY_ID: "{{ restic_s3_key }}"
AWS_SECRET_ACCESS_KEY: "{{ restic_s3_secret }}"
{% if restic_notify_success != None %}
POST_COMMANDS_SUCCESS: |-
curl -X POST --data "{\"title\": \"Restic Prune successful\", \"body\": \"{{ ansible_hostname }}\"}" http://notify_success:5000
{% endif %}
{% if restic_notify_failure != None %}
POST_COMMANDS_FAILURE: |-
curl -X POST --data "{\"title\": \"Restic Prune failed\", \"body\": \"{{ ansible_hostname }}\"}" http://notify_failure:5000
{% endif %}
{% if restic_notify_exit != None %}
POST_COMMANDS_EXIT: |-
curl -X POST --data "{\"title\": \"Restic Prune exited\", \"body\": \"{{ ansible_hostname }}\"}" http://notify_exit:5000
{% endif %}
{% if restic_repo is regex('^/.+') %}
volumes:
- "{{ restic_repo }}:{{ restic_repo }}"
{% endif %}
check:
image: "mazzolino/restic:{{ restic_version }}"
hostname: docker
networks:
- restic_notify
environment:
TZ: "{{ restic_tz }}"
SKIP_INIT: true
RUN_ON_STARTUP: true
CHECK_CRON: "{{ restic_check_cron }}"
RESTIC_CHECK_ARGS: "{{ restic_check_args }}"
RESTIC_REPOSITORY: "{{ restic_repo }}"
RESTIC_PASSWORD: "{{ restic_pass }}"
AWS_ACCESS_KEY_ID: "{{ restic_s3_key }}"
AWS_SECRET_ACCESS_KEY: "{{ restic_s3_secret }}"
{% if restic_notify_success != None %}
POST_COMMANDS_SUCCESS: |-
curl -X POST --data "{\"title\": \"Restic Check successful\", \"body\": \"{{ ansible_hostname }}\"}" http://notify_success:5000
{% endif %}
{% if restic_notify_failure != None %}
POST_COMMANDS_FAILURE: |-
curl -X POST --data "{\"title\": \"Restic Check failed\", \"body\": \"{{ ansible_hostname }}\"}" http://notify_failure:5000
{% endif %}
{% if restic_notify_exit != None %}
POST_COMMANDS_EXIT: |-
curl -X POST --data "{\"title\": \"Restic Check exited\", \"body\": \"{{ ansible_hostname }}\"}" http://notify_exit:5000
{% endif %}
{% if restic_repo is regex('^/.+') %}
volumes:
- "{{ restic_repo }}:{{ restic_repo }}"
{% endif %}
{% if restic_notify_success != None %}
notify_success:
image: mazzolino/apprise-microservice:latest
networks:
- restic_notify
environment:
NOTIFICATION_URLS: {{ restic_notify_success }}
{% endif %}
{% if restic_notify_failure != None %}
notify_failure:
image: mazzolino/apprise-microservice:latest
networks:
- restic_notify
environment:
NOTIFICATION_URLS: {{ restic_notify_failure }}
{% endif %}
{% if restic_notify_exit != None %}
notify_exit:
image: mazzolino/apprise-microservice:latest
networks:
- restic_notify
environment:
NOTIFICATION_URLS: {{ restic_notify_exit }}
{% endif %}
networks:
restic_notify:

View file

@ -0,0 +1,8 @@
---
stack_name: restic
stack_image: "mazzolino/restic"
stack_compose: "{{ lookup('template', 'docker-stack.yml.j2') | from_yaml }}"
backup_enable: true