initial commit

This commit is contained in:
Robert Kaussow 2020-01-17 22:00:14 +01:00
commit 902c508584
23 changed files with 722 additions and 0 deletions

141
.drone.jsonnet Normal file
View File

@ -0,0 +1,141 @@
local PipelineLinting = {
kind: "pipeline",
name: "linting",
platform: {
os: "linux",
arch: "amd64",
},
steps: [
{
name: "ansible-later",
image: "xoxys/ansible-later:latest",
commands: [
"ansible-later",
],
},
],
trigger: {
ref: ["refs/heads/master", "refs/tags/**", "refs/pull/**"],
},
};
local PipelineDeployment = {
kind: "pipeline",
name: "deployment",
platform: {
os: "linux",
arch: "amd64",
},
concurrency: {
limit: 1
},
workspace: {
base: "/drone/src",
path: "xoxys.bitwarden_rs"
},
steps: [
{
name: "ansible-molecule",
image: "xoxys/molecule:latest",
environment: {
DO_API_KEY: { "from_secret": "do_api_key" },
USER: "root",
MOLECULE_CUSTOM_MODULES_REPO: "https://gitea.rknet.org/ansible/custom_modules",
MOLECULE_CUSTOM_FILTERS_REPO: "https://gitea.rknet.org/ansible/custom_filters",
},
commands: [
"molecule test -s default",
],
},
],
depends_on: [
"linting",
],
trigger: {
ref: ["refs/heads/master", "refs/tags/**"],
},
};
local PipelineDocumentation = {
kind: "pipeline",
name: "documentation",
platform: {
os: "linux",
arch: "amd64",
},
steps: [
{
name: "ansible-doctor",
image: "xoxys/ansible-doctor:latest",
environment: {
ANSIBLE_DOCTOR_LOG_LEVEL: "INFO",
ANSIBLE_DOCTOR_FORCE_OVERWRITE: true,
ANSIBLE_DOCTOR_EXCLUDE_FILES: "molecule/",
ANSIBLE_DOCTOR_CUSTOM_HEADER: "HEADER.md",
},
},
{
name: "push-to-repo",
image: "plugins/git-action:latest",
settings: {
actions: ["commit", "push"],
author_email: "shipper@rknet.org",
author_name: "DroneShipper",
branch: "master",
message: "[SKIP CI] update readme",
remote: "https://gitea.rknet.org/ansible/xoxys.bitwarden_rs",
netrc_machine: "gitea.rknet.org",
netrc_username: {"from_secret": "gitea_username"},
netrc_password: {"from_secret": "gitea_token"},
},
when: {
ref: ["refs/heads/master"],
},
},
],
depends_on: [
"deployment",
],
trigger: {
ref: ["refs/heads/master", "refs/tags/**", "refs/pull/**"],
},
};
local PipelineNotification= {
kind: "pipeline",
name: "notification",
platform: {
os: "linux",
arch: "amd64",
},
clone: {
disable: true,
},
steps: [
{
name: "matrix",
image: "plugins/matrix",
settings: {
homeserver: { "from_secret": "matrix_homeserver" },
roomid: { "from_secret": "matrix_roomid" },
template: "Status: **{{ build.status }}**<br/> Build: [{{ repo.Owner }}/{{ repo.Name }}]({{ build.link }}) ({{ build.branch }}) by {{ build.author }}<br/> Message: {{ build.message }}",
username: { "from_secret": "matrix_username" },
password: { "from_secret": "matrix_password" },
},
},
],
depends_on: [
"documentation",
],
trigger: {
status: [ "success", "failure" ],
ref: ["refs/heads/master", "refs/tags/**"],
},
};
[
PipelineLinting,
PipelineDeployment,
PipelineDocumentation,
PipelineNotification,
]

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
# ---> Ansible
*.retry
plugins
library
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

18
.later.yml Normal file
View File

@ -0,0 +1,18 @@
---
ansible:
custom_modules:
- iptables_raw
- openssl_pkcs12
- proxmox_kvm2
- ucr
- yum_versionlock
rules:
exclude_files:
- molecule/
- "LICENSE*"
- "**/*.md"
- "**/*.ini"
exclude_filter:
- LINT0009

4
HEADER.md Normal file
View File

@ -0,0 +1,4 @@
# xoxys.bitwarden_rs
[![Build Status](https://drone.rknet.org/api/badges/ansible/xoxys.bitwarden_rs/status.svg)](https://drone.rknet.org/ansible/xoxys.bitwarden_rs)

8
LICENSE Normal file
View File

@ -0,0 +1,8 @@
MIT License
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# xoxys.bitwarden_rs

89
defaults/main.yml Normal file
View File

@ -0,0 +1,89 @@
---
bitwardenrs_version: latest
bitwardenrs_service_directory: /var/lib/docker/services/bitwardenrs
bitwardenrs_container_name: bitwardenrs
bitwardenrs_image: "xoxys/bitwardenrs:{{ bitwardenrs_version }}"
bitwardenrs_restart_policy: on-failure
bitwardenrs_exposed_port: 80
bitwardenrs_exposed_ip: 127.0.0.1
bitwardenrs_extra_hosts: []
# @var bitwardenrs_memory_limit: $ "_unset_"
# @var bitwardenrs_memory_limit:example: $ "512m"
# @var bitwardenrs_memory_reservation: $ "_unset_"
# @var bitwardenrs_memory_reservation:example: $ "256m"
# @var bitwardenrs_cpu_shares: $ "_unset_"
# @var bitwardenrs_cpu_shares:example: $ "1024"
bitwardenrs_cap_add: []
bitwardenrs_cap_drop: []
bitwardenrs_security_opt: []
# @var bitwardenrs_pids_limit: $ "_unset_"
bitwardenrs_healthcheck:
test: '["CMD", "/usr/local/bin/healthcheck.sh"]'
interval: 30s
timeout: 5s
retries: 5
bitwardenrs_base_url: "http://localhost/"
# @var bitwardenrs_templates_folder: $ "_unset_"
bitwardenrs_reload_templates: False
bitwardenrs_ip_header: x-client-ip
bitwardenrs_icon_cache_ttl: 2592000
bitwardenrs_icon_cache_negttl: "{{ bitwardenrs_icon_cache_ttl }}"
bitwardenrs_web_vault_enabled: True
bitwardenrs_extended_logging: True
bitwardenrs_log_level: Info
bitwardenrs_disable_icon_download: False
bitwardenrs_icon_download_timeout: 10
# @var bitwardenrs_icon_blacklist_regexl: $ "_unset_"
bitwardenrs_icon_blacklist_non_global_ips: True
bitwardenrs_disable_2fa_remember: False
bitwardenrs_signups_allowed: False
bitwardenrs_signups_verify: False
bitwardenrs_signups_verify_resend_time: 3600
bitwardenrs_signups_verify_resend_limit: 6
# @var bitwardenrs_signups_domains_whitelist: $ "_unset_"
bitwardenrs_invitations_allowed: True
# @var bitwardenrs_admin_token: $ "_unset_"
bitwardenrs_password_iterations: 100000
bitwardenrs_show_password_hint: True
bitwardenrs_authenticator_disable_time_drift: False
# @var bitwardenrs_smtp_host: $ "_unset_"
bitwardenrs_smtp_from: "bitwardenrs@localhost"
bitwardenrs_smtp_from_name: "bitwarden_rs"
bitwardenrs_smtp_port: 587
bitwardenrs_smtp_ssl: True
# @var bitwardenrs_smtp_username: $ "_unset_"
# @var bitwardenrs_smtp_password: $ "_unset_"
bitwardenrs_smtp_auth_mechanism: plain
bitwardenrs_smtp_timeout: 15
# @var bitwardenrs_db_server:description: >
# This ansible roles does only support postgresql as database"
# @end
bitwardenrs_db_server: localhost
bitwardenrs_db_port: 5432
bitwardenrs_db_name: bitwardenrs
bitwardenrs_db_user: pgbitwardenrs
bitwardenrs_db_password: secure
bitwardenrs_db_ssl_mode: disable
bitwardenrs_db_ssl_rootcert: /etc/ssl/certs/ca-certificates.crt
bitwardenrs_docker_compose_bin: /usr/local/bin/docker-compose

9
handlers/main.yml Normal file
View File

@ -0,0 +1,9 @@
---
- name: Restart container
systemd:
state: restarted
daemon_reload: yes
name: bitwardenrs
listen: __bitwardenrs_restart
become: True
become_user: root

18
meta/main.yml Normal file
View File

@ -0,0 +1,18 @@
# Standards: 0.1
---
galaxy_info:
# @meta author:value: [xoxys](https://gitea.rknet.org/xoxys)
author: xoxys <mail@geeklabor.de>
description: Role to setup Bitwarden passsword save
license: MIT
min_ansible_version: 2.4
platforms:
- name: EL
versions:
- 7
galaxy_tags:
- security
- vault
- password
- save
dependencies:

View File

@ -0,0 +1,87 @@
---
- name: Create
hosts: localhost
connection: local
gather_facts: false
no_log: "{{ molecule_no_log }}"
vars:
ssh_user: root
ssh_port: 22
keypair_name: molecule_key
keypair_path: "{{ lookup('env', 'MOLECULE_EPHEMERAL_DIRECTORY') }}/ssh_key"
tasks:
- name: Create local keypair
user:
name: "{{ lookup('env', 'USER') }}"
generate_ssh_key: true
ssh_key_file: "{{ keypair_path }}"
register: local_keypair
- name: Create remote keypair
digital_ocean_sshkey:
name: "{{ keypair_name }}"
ssh_pub_key: "{{ local_keypair.ssh_public_key }}"
state: present
register: remote_keypair
- name: Create molecule instance(s)
digital_ocean_droplet:
name: "{{ item.name }}"
unique_name: true
region: "{{ item.region_id }}"
image: "{{ item.image_id }}"
size: "{{ item.size_id }}"
ssh_keys: "{{ remote_keypair.data.ssh_key.id }}"
wait: true
wait_timeout: 300
state: present
register: server
loop: "{{ molecule_yml.platforms }}"
async: 7200
poll: 0
- name: Wait for instance(s) creation to complete
async_status:
jid: "{{ item.ansible_job_id }}"
register: digitalocean_jobs
until: digitalocean_jobs.finished
retries: 300
loop: "{{ server.results }}"
# Mandatory configuration for Molecule to function.
- name: Populate instance config dict
set_fact:
instance_conf_dict: {
'instance': "{{ item.data.droplet.name }}",
'address': "{{ item.data.ip_address }}",
'user': "{{ ssh_user }}",
'port': "{{ ssh_port }}",
'identity_file': "{{ keypair_path }}",
'droplet_id': "{{ item.data.droplet.id }}",
'ssh_key_id': "{{ remote_keypair.data.ssh_key.id }}",
}
loop: "{{ digitalocean_jobs.results }}"
register: instance_config_dict
when: server.changed | bool
- name: Convert instance config dict to a list
set_fact:
instance_conf: "{{ instance_config_dict.results | map(attribute='ansible_facts.instance_conf_dict') | list }}"
when: server.changed | bool
- name: Dump instance config
copy:
content: "{{ instance_conf | to_json | from_json | molecule_to_yaml | molecule_header }}"
dest: "{{ molecule_instance_config }}"
when: server.changed | bool
- name: Wait for SSH
wait_for:
port: "{{ ssh_port }}"
host: "{{ item.address }}"
search_regex: SSH
delay: 10
timeout: 320
loop: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}"

View File

@ -0,0 +1,54 @@
---
- name: Destroy
hosts: localhost
connection: local
gather_facts: false
no_log: "{{ molecule_no_log }}"
tasks:
- block:
- name: Populate instance config
set_fact:
instance_conf: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}"
skip_instances: false
rescue:
- name: Populate instance config when file missing
set_fact:
instance_conf: {}
skip_instances: true
- name: Destroy molecule instance(s)
digital_ocean_droplet:
name: "{{ item.instance }}"
id: "{{ item.droplet_id }}"
state: absent
register: server
loop: "{{ instance_conf | flatten(levels=1) }}"
when: not skip_instances
async: 7200
poll: 0
- name: Wait for instance(s) deletion to complete
async_status:
jid: "{{ item.ansible_job_id }}"
register: digitalocean_jobs
until: digitalocean_jobs.finished
retries: 300
loop: "{{ server.results }}"
- name: Delete remote keypair
digital_ocean_sshkey:
fingerprint: "{{ item.ssh_key_id }}"
state: absent
loop: "{{ instance_conf | flatten(levels=1) }}"
# Mandatory configuration for Molecule to function.
- name: Populate instance config
set_fact:
instance_conf: {}
- name: Dump instance config
copy:
content: "{{ instance_conf | molecule_to_yaml | molecule_header }}"
dest: "{{ molecule_instance_config }}"
when: server.changed | bool

View File

@ -0,0 +1,24 @@
---
dependency:
name: galaxy
driver:
name: digitalocean
platforms:
- name: centos7-bitwarden_rs
region_id: fra1
image_id: centos-7-x64
size_id: s-1vcpu-1gb
lint:
name: yamllint
enabled: False
provisioner:
name: ansible
lint:
name: ansible-lint
enabled: False
verifier:
name: testinfra
lint:
name: flake8
options:
max-line-length: 120

View File

@ -0,0 +1,33 @@
---
- name: Converge (Stage 1)
hosts: all
roles:
- role: xoxys.python3
- role: xoxys.docker-engine
- name: Converge (Stage 2)
hosts: all
vars:
postgres_repository_enabled: True
postgres_connection_addresses:
- "{{ ansible_docker0.ipv4.address }}"
postgres_users:
- name: "pgbitwardenrs"
password: "secure"
priv: ALL
db: "bitwardenrs"
postgres_dbs:
- name: "bitwardenrs"
postgres_hba_entries_extra:
- contype: host
databases:
- all
users:
- all
address: "172.18.0.0/16"
auth_method: md5
bitwardenrs_db_server: "{{ ansible_docker0.ipv4.address }}"
roles:
- role: xoxys.postgres
- role: xoxys.bitwardenrs

View File

@ -0,0 +1,9 @@
---
- name: Prepare
hosts: all
gather_facts: false
tasks:
- name: Install python for Ansible
raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)
become: true
changed_when: false

View File

@ -0,0 +1,15 @@
---
- src: https://gitea.rknet.org/ansible/xoxys.python3.git
name: xoxys.python3
scm: git
version: master
- src: https://gitea.rknet.org/ansible/xoxys.docker-engine.git
name: xoxys.docker-engine
scm: git
version: master
- src: https://gitea.rknet.org/ansible/xoxys.postgres.git
name: xoxys.postgres
scm: git
version: master

View File

@ -0,0 +1,28 @@
import os
import testinfra.utils.ansible_runner
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
def test_bitwarden_rs_running(host):
bitwarden_rs = host.docker("bitwarden_rs")
assert bitwarden_rs.is_running
def test_bitwarden_rs_socket(host):
# Verify the socket is listening for HTTP traffic
assert host.socket("tcp://127.0.0.1:80").is_listening
def test_bitwarden_rs_conn_error(host):
code = int(host.run("curl -s -w '%{http_code}' http://localhost/alive -o /dev/null").stdout)
body = host.run("curl -sX GET http://localhost/").stdout
assert code == 200
assert "Bitwarden Web Vault" in body

3
molecule/pytest.ini Normal file
View File

@ -0,0 +1,3 @@
[pytest]
filterwarnings =
ignore::DeprecationWarning

4
tasks/main.yml Normal file
View File

@ -0,0 +1,4 @@
---
- include_tasks: prepare.yml
- include_tasks: setup.yml
- include_tasks: post.yml

10
tasks/post.yml Normal file
View File

@ -0,0 +1,10 @@
---
- block:
- name: Ensure bitwardenrs service is up and running
systemd:
state: started
daemon_reload: yes
enabled: yes
name: bitwardenrs
become: True
become_user: root

8
tasks/prepare.yml Normal file
View File

@ -0,0 +1,8 @@
---
- name: Ensure service directory exists
file:
path: "{{ bitwardenrs_service_directory }}"
state: directory
mode: 0755
become: True
become_user: root

20
tasks/setup.yml Normal file
View File

@ -0,0 +1,20 @@
---
- block:
- name: Deploy compose file to '{{ bitwardenrs_service_directory }}'
template:
src: "services/compose.yml.j2"
dest: "{{ bitwardenrs_service_directory }}/docker-compose.yml"
owner: root
group: root
mode: 0644
validate: "{{ bitwardenrs_docker_compose_bin }} -f %s config -q"
notify: __bitwardenrs_restart
- name: Create systemd unit files
template:
src: "etc/systemd/system/bitwardenrs.service.j2"
dest: "/etc/systemd/system/bitwardenrs.service"
mode: 0644
notify: __bitwardenrs_restart
become: True
become_user: root

View File

@ -0,0 +1,22 @@
#jinja2:lstrip_blocks: True
{{ ansible_managed | comment }}
[Unit]
Description=TT-RSS news feed reader
Requires=docker.service network-online.target
After=docker.service network-online.target
[Service]
WorkingDirectory={{ bitwardenrs_service_directory }}
Type=simple
TimeoutStartSec=15min
Restart={{ bitwardenrs_restart_policy }}
ExecStartPre={{ bitwardenrs_docker_compose_bin }} pull --quiet --ignore-pull-failures
ExecStart={{ bitwardenrs_docker_compose_bin }} up --remove-orphans
ExecStop={{ bitwardenrs_docker_compose_bin }} down --remove-orphans
ExecReload={{ bitwardenrs_docker_compose_bin }} pull --quiet --ignore-pull-failures
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,105 @@
#jinja2:lstrip_blocks: True
{{ ansible_managed | comment }}
version: '2.1'
services:
bitwardenrs:
container_name: {{ bitwardenrs_container_name }}
image: {{ bitwardenrs_image }}
restart: unless-stopped
ports:
- {{ bitwardenrs_exposed_ip + ':' if bitwardenrs_exposed_ip is defined else '' }}{{ bitwardenrs_exposed_port }}:8080
volumes:
- data:/app/data
{% if bitwardenrs_extra_hosts | default([]) %}
extra_hosts:
{% for host in bitwardenrs_extra_hosts %}
- {{ '"' + host + '"' }}
{% endfor %}
{% endif %}
environment:
- BITWARDENRS_BASE_URL={{ bitwardenrs_base_url }}
- BITWARDENRS_DATABASE_URL=postgresql://{{ bitwardenrs_db_user }}:{{ bitwardenrs_db_password }}@{{ bitwardenrs_db_server }}:{{ bitwardenrs_db_port }}/{{ bitwardenrs_db_name }}?{{ bitwardenrs_db_ssl_mode }}
{% if bitwardenrs_templates_folder is defined and bitwardenrs_templates_folder %}
- BITWARDENRS_TEMPLATES_FOLDER={{ bitwardenrs_templates_folder }}
{% endif %}
- BITWARDENRS_RELOAD_TEMPLATES={{ bitwardenrs_reload_templates }}
- BITWARDENRS_IP_HEADER={{ bitwardenrs_ip_header }}
- BITWARDENRS_ICON_CACHE_TTL={{ bitwardenrs_icon_cache_ttl }}
- BITWARDENRS_ICON_CACHE_NEGTTL="{{ bitwardenrs_icon_cache_negttl }}"
- BITWARDENRS_WEB_VAULT_ENABLED={{ bitwardenrs_web_vault_enabled }}
- BITWARDENRS_EXTENDED_LOGGING={{ bitwardenrs_extended_logging }}
- BITWARDENRS_LOG_LEVEL={{ bitwardenrs_log_level }}
- BITWARDENRS_DISABLE_ICON_DOWNLOAD={{ bitwardenrs_disable_icon_download }}
- BITWARDENRS_ICON_DOWNLOAD_TIMEOUT={{ bitwardenrs_icon_download_timeout }}
{% if bitwardenrs_icon_blacklist_regexl is defined and bitwardenrs_icon_blacklist_regexl %}
- BITWARDENRS_ICON_BLACKLIST_REGEXL={{ bitwardenrs_icon_blacklist_regexl }}
{% endif %}
- BITWARDENRS_ICON_BLACKLIST_NON_GLOBAL_IPS={{ bitwardenrs_icon_blacklist_non_global_ips }}
- BITWARDENRS_DISABLE_2FA_REMEMBER={{ bitwardenrs_disable_2fa_remember }}
- BITWARDENRS_SIGNUPS_ALLOWED={{ bitwardenrs_signups_allowed }}
- BITWARDENRS_SIGNUPS_VERIFY={{ bitwardenrs_signups_verify }}
- BITWARDENRS_SIGNUPS_VERIFY_RESEND_TIME={{ bitwardenrs_signups_verify_resend_time }}
- BITWARDENRS_SIGNUPS_VERIFY_RESEND_LIMIT={{ bitwardenrs_signups_verify_resend_limit }}
{% if bitwardenrs_signups_domains_whitelist is defined and bitwardenrs_signups_domains_whitelist %}
- BITWARDENRS_SIGNUPS_DOMAINS_WHITELIST={{ bitwardenrs_signups_domains_whitelist }}
{% endif %}
- BITWARDENRS_INVITATIONS_ALLOWED={{ bitwardenrs_invitations_allowed }}
{% if bitwardenrs_admin_token is defined and bitwardenrs_admin_token %}
- BITWARDENRS_ADMIN_TOKEN={{ bitwardenrs_admin_token }}
{% endif %}
- BITWARDENRS_PASSWORD_ITERATIONS={{ bitwardenrs_password_iterations }}
- BITWARDENRS_SHOW_PASSWORD_HINT={{ bitwardenrs_show_password_hint }}
- BITWARDENRS_AUTHENTICATOR_DISABLE_TIME_DRIFT={{ bitwardenrs_authenticator_disable_time_drift }}
{% if bitwardenrs_smtp_host is defined and bitwardenrs_smtp_host %}
- BITWARDENRS_SMTP_HOST={{ bitwardenrs_smtp_host }}
{% endif %}
- BITWARDENRS_SMTP_FROM={{ bitwardenrs_smtp_from }}
- BITWARDENRS_SMTP_FROM_NAME={{ bitwardenrs_smtp_from_name }}
- BITWARDENRS_SMTP_PORT={{ bitwardenrs_smtp_port }}
- BITWARDENRS_SMTP_SSL={{ bitwardenrs_smtp_ssl }}
{% if bitwardenrs_smtp_username is defined and bitwardenrs_smtp_username %}
- BITWARDENRS_SMTP_USERNAME={{ bitwardenrs_smtp_username }}
- BITWARDENRS_SMTP_PASSWORD={{ bitwardenrs_smtp_password }}
{% endif %}
- BITWARDENRS_SMTP_AUTH_MECHANISM={{ bitwardenrs_smtp_auth_mechanism }}
- BITWARDENRS_SMTP_TIMEOUT={{ bitwardenrs_smtp_timeout }}
{% if bitwardenrs_memory_limit is defined %}
mem_limit: {{ bitwardenrs_memory_limit }}
{% endif %}
{% if bitwardenrs_memory_reservation is defined %}
mem_reservation: {{ bitwardenrs_memory_reservation }}
{% endif %}
{% if bitwardenrs_cpu_shares is defined %}
cpu_shares: {{ bitwardenrs_cpu_shares }}
{% endif %}
{% if not bitwardenrs_cap_add | length == 0 %}
cap_add:
{% for item in bitwardenrs_cap_add %}
- {{ item }}
{% endfor %}
{% endif %}
{% if not bitwardenrs_cap_drop | length == 0 %}
cap_drop:
{% for item in bitwardenrs_cap_drop %}
- {{ item }}
{% endfor %}
{% endif %}
{% if not bitwardenrs_security_opt | length == 0 %}
security_opt:
{% for item in bitwardenrs_security_opt %}
- {{ item }}
{% endfor %}
{% endif %}
healthcheck:
{% for key, value in bitwardenrs_healthcheck.items() %}
{{ key }}: {{ value }}
{% endfor %}
{% if bitwardenrs_pids_limit is defined %}
pids_limit: {{ bitwardenrs_pids_limit }}
{% endif %}
volumes:
data:
driver: local