26 Commits

Author SHA1 Message Date
436c3a76da feat(snipe_it): add ansible role for deployment 2024-10-20 13:58:40 +02:00
5ac019bace docs: fix typo 2024-10-19 17:33:13 +02:00
43fd798712 feat(vaultwarden): add ansible role 2024-10-19 17:26:50 +02:00
88dc6377ce fix(hedgedoc): incorrect module used 2024-10-19 17:13:24 +02:00
0a132b0ad5 meta: update collection version to 0.1.5, add galaxy tags 2024-10-10 17:01:35 +02:00
72942ee382 update(hedgedoc): bump version to 1.10.0 2024-10-10 16:59:06 +02:00
755e5d55f2 update(ghost): bump version to 5.96.0 2024-10-10 16:58:01 +02:00
5023a56b29 update(authelia): bump version to 4.38.15 2024-10-10 16:56:49 +02:00
17dfe4b2bb update(gitea): bump version to 1.22.3 2024-10-10 16:55:57 +02:00
cd122ebbdb fix(gitea): typo in variable name 2024-10-10 16:55:27 +02:00
0d914bd11c feat(hedgedoc): add deployment_method=podman, add docs 2024-10-09 20:06:48 +02:00
49ed240f10 fix(hedgedoc): add options ports and user to container creation task 2024-10-08 17:55:06 +02:00
81d6f809d7 meta: bump collection version to 0.1.4 2024-10-07 19:44:08 +02:00
b24ea1e925 feat(jellyfin): add playbook to collection, add state=absent support to role 2024-10-07 19:42:22 +02:00
912c32cb3e feat(hedgedoc): add ansible role for deployment 2024-10-07 19:09:52 +02:00
cde5f12e79 meta: bump galaxy version to 0.1.3 2024-10-03 22:37:43 +02:00
a8f5507eab meta: add role descriptions 2024-10-03 22:34:28 +02:00
ddfa8d6687 chore(jellyfin): migrate to fully-qualified module names 2024-10-03 22:25:46 +02:00
fd4cc0fe6a meta: require community.crypto@^2.0.0 in collection 2024-10-03 22:24:30 +02:00
3a15ed1157 chore(gitea): migrate to fully-qualified module names 2024-10-03 22:22:31 +02:00
a7fad79d05 chore(authelia): add container recreation option 2024-10-03 22:19:16 +02:00
f3d3617ec0 chore(authelia): migrate to fully-qualified module names 2024-10-03 22:18:34 +02:00
908b579f2c chore(authelia): more config migration in preparation for authelia 5.0.x 2024-10-03 22:05:08 +02:00
bab5b94500 update(ghost): bump version to 5.95.0 2024-10-03 21:30:48 +02:00
b5b4f67a08 chore(authelia): migrate away from deprecated config options 2024-10-03 18:01:40 +02:00
5e29e174d5 chore(authelia): add etc_hosts container option 2024-10-03 17:06:49 +02:00
49 changed files with 1037 additions and 54 deletions

View File

@ -1,4 +1,4 @@
# `finallycoffee.service` ansible collection
# `finallycoffee.services` ansible collection
## Overview
@ -17,12 +17,18 @@ concise area of concern.
- [`gitea`](roles/gitea/README.md): Deploy [gitea.io](https://gitea.io), a
lightweight, self-hosted git service.
- [`hedgedoc`](roles/hedgedoc/README.md): Deploy [hedgedoc](https://hedgedoc.org/),
a collaborative real-time markdown editor using websockts
- [`jellyfin`](roles/jellyfin/README.md): Deploy [jellyfin.org](https://jellyfin.org),
the free software media system for streaming stored media to any device.
- [`openproject`](roles/openproject/README.md): Deploys an [openproject.org](https://www.openproject.org)
installation using the upstream provided docker-compose setup.
- [`vaultwarden`](roles/vaultwarden/README.md): Deploy [vaultwarden](https://github.com/dani-garcia/vaultwarden/),
an open-source implementation of the Bitwarden Server (formerly Bitwarden\_RS).
- [`vouch_proxy`](roles/vouch_proxy/README.md): Deploys [vouch-proxy](https://github.com/vouch/vouch-proxy),
an authorization proxy for arbitrary webapps working with `nginx`s' `auth_request` module.

View File

@ -1,14 +1,22 @@
namespace: finallycoffee
name: services
version: 0.1.2
version: 0.1.5
readme: README.md
authors:
- transcaffeine <transcaffeine@finally.coffee>
description: Various ansible roles useful for automating infrastructure
dependencies:
"community.crypto": "^2.0.0"
"community.docker": "^3.0.0"
license_file: LICENSE.md
build_ignore:
- '*.tar.gz'
repository: https://git.finally.coffee/finallycoffee/services
issues: https://codeberg.org/finallycoffee/ansible-collection-services/issues
tags:
- authelia
- gitea
- hedgedoc
- jellyfin
- vaultwarden
- docker

6
playbooks/hedgedoc.yml Normal file
View File

@ -0,0 +1,6 @@
---
- name: Install and configure hedgedoc
hosts: "{{ hedgedoc_hosts | default('hedgedoc') }}"
become: "{{ hedgedoc_become | default(true, false) }}"
roles:
- role: finallycoffee.services.hedgedoc

6
playbooks/jellyfin.yml Normal file
View File

@ -0,0 +1,6 @@
---
- name: Install and configure jellyfin
hosts: "{{ jellyfin_hosts | default('jellyfin') }}"
become: "{{ jellyfin_become | default(true, false) }}"
roles:
- role: finallycoffee.services.jellyfin

View File

@ -0,0 +1,6 @@
---
- name: Install and configure vaultwarden
hosts: "{{ vaultwarden_hosts | default('vaultwarden') }}"
become: "{{ vaultwarden_become | default(true, false) }}"
roles:
- role: finallycoffee.services.vaultwarden

View File

@ -1,6 +1,5 @@
---
authelia_version: 4.38.15
authelia_version: "4.38.16"
authelia_user: authelia
authelia_base_dir: /opt/authelia
authelia_domain: authelia.example.org
@ -57,10 +56,18 @@ authelia_config_server_address: >-2
{{ authelia_config_server_host }}:{{ authelia_config_server_port }}
authelia_config_server_path: ""
authelia_config_server_asset_path: "/config/assets/"
authelia_config_server_read_buffer_size: 4096
authelia_config_server_write_buffer_size: 4096
authelia_config_server_enable_pprof: true
authelia_config_server_enable_expvars: true
authelia_config_server_buffers_read: 4096
authelia_config_server_read_buffer_size: >-2
{{ authelia_config_server_buffers_read }}
authelia_config_server_buffers_write: 4096
authelia_config_server_write_buffer_size: >-2
{{ authelia_config_server_buffers_write }}
authelia_config_server_endpoints_enable_pprof: true
authelia_config_server_enable_pprof: >-2
{{ authelia_config_server_endpoints_enable_pprof }}
authelia_config_server_endpoints_enable_expvars: true
authelia_config_server_enable_expvars: >-2
{{ authelia_config_server_endpoints_enable_expvars }}
authelia_config_server_disable_healthcheck:
authelia_config_server_tls_key: ~
authelia_config_server_tls_certificate: ~
@ -107,10 +114,18 @@ authelia_config_authentication_backend_ldap_additional_users_dn: "ou=users"
authelia_config_authentication_backend_ldap_users_filter: "(&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=inetOrgPerson))"
authelia_config_authentication_backend_ldap_additional_groups_dn: "ou=groups"
authelia_config_authentication_backend_ldap_groups_filter: "(member={dn})"
authelia_config_authentication_backend_ldap_attributes_username: uid
authelia_config_authentication_backend_ldap_username_attribute: >-2
{{ authelia_config_authentication_backend_ldap_attributes_username }}
authelia_config_authentication_backend_ldap_attributes_mail: mail
authelia_config_authentication_backend_ldap_mail_attribute: >-2
{{ authelia_config_authentication_backend_ldap_attributes_mail }}
authelia_config_authentication_backend_ldap_attributes_display_name: displayName
authelia_config_authentication_backend_ldap_display_name_attribute: >-2
{{ authelia_config_authentication_backend_ldap_attributes_display_name }}
authelia_config_authentication_backend_ldap_group_name_attribute: cn
authelia_config_authentication_backend_ldap_username_attribute: uid
authelia_config_authentication_backend_ldap_mail_attribute: mail
authelia_config_authentication_backend_ldap_display_name_attribute: displayName
authelia_config_authentication_backend_ldap_attributes_group_name: >-2
{{ authelia_config_authentication_backend_ldap_group_name_attribute }}
authelia_config_authentication_backend_ldap_user: ~
authelia_config_authentication_backend_ldap_password: ~
authelia_config_authentication_backend_file_path: ~
@ -138,6 +153,8 @@ authelia_config_session_secret: ~
authelia_config_session_expiration: 1h
authelia_config_session_inactivity: 5m
authelia_config_session_remember_me_duration: 1M
authelia_config_session_remember_me: >-2
{{ authelia_config_session_remember_me_duration }}
authelia_config_session_redis_host: "{{ authelia_redis_host }}"
authelia_config_session_redis_port: "{{ authelia_redis_port }}"
authelia_config_session_redis_username: "{{ authelia_redis_user }}"

View File

@ -0,0 +1,9 @@
---
allow_duplicates: true
dependencies: []
galaxy_info:
role_name: authelia
description: Ansible role to deploy authelia using docker
galaxy_tags:
- authelia
- docker

View File

@ -1,14 +1,14 @@
---
- name: Ensure user {{ authelia_user }} exists
user:
ansible.builtin.user:
name: "{{ authelia_user }}"
state: present
system: true
register: authelia_user_info
- name: Ensure host directories are created with correct permissions
file:
ansible.builtin.file:
path: "{{ item.path }}"
state: directory
owner: "{{ item.owner | default(authelia_user) }}"
@ -26,7 +26,7 @@
mode: "0750"
- name: Ensure config file is generated
copy:
ansible.builtin.copy:
content: "{{ authelia_config | to_nice_yaml(indent=2, width=10000) }}"
dest: "{{ authelia_config_file }}"
owner: "{{ authelia_run_user }}"
@ -35,7 +35,7 @@
notify: restart-authelia
- name: Ensure sqlite database file exists before mounting it
file:
ansible.builtin.file:
path: "{{ authelia_sqlite_storage_file }}"
state: touch
owner: "{{ authelia_run_user }}"
@ -46,7 +46,7 @@
when: authelia_config_storage_local_path | default(false, true)
- name: Ensure user database exists before mounting it
file:
ansible.builtin.file:
path: "{{ authelia_user_storage_file }}"
state: touch
owner: "{{ authelia_run_user }}"
@ -57,7 +57,7 @@
when: authelia_config_authentication_backend_file_path | default(false, true)
- name: Ensure notification reports file exists before mounting it
file:
ansible.builtin.file:
path: "{{ authelia_notification_storage_file }}"
state: touch
owner: "{{ authelia_run_user }}"
@ -76,7 +76,7 @@
register: authelia_container_image_info
- name: Ensure authelia container is running
docker_container:
community.docker.docker_container:
name: "{{ authelia_container_name }}"
image: "{{ authelia_container_image_ref }}"
env: "{{ authelia_container_env }}"
@ -85,7 +85,9 @@
labels: "{{ authelia_container_labels }}"
volumes: "{{ authelia_container_volumes }}"
networks: "{{ authelia_container_networks | default(omit, true) }}"
etc_hosts: "{{ authelia_container_etc_hosts | default(omit, true) }}"
purge_networks: "{{ authelia_container_purge_networks | default(omit, true)}}"
restart_policy: "{{ authelia_container_restart_policy }}"
recreate: "{{ authelia_container_recreate | default(omit, true) }}"
state: "{{ authelia_container_state }}"
register: authelia_container_info

View File

@ -50,14 +50,18 @@ authelia_config_server: >-2
{
"address": authelia_config_server_address,
"asset_path": authelia_config_server_asset_path,
"read_buffer_size": authelia_config_server_read_buffer_size,
"write_buffer_size": authelia_config_server_write_buffer_size,
"enable_pprof": authelia_config_server_enable_pprof,
"enable_expvars": authelia_config_server_enable_expvars,
"disable_healthcheck": authelia_config_server_disable_healthcheck,
"endpoints": authelia_config_server_endpoints,
"buffers": authelia_config_server_buffers,
} | combine({"headers": {"csp_template": authelia_config_server_headers_csp_template}}
if authelia_config_server_headers_csp_template | default(false, true) else {})
}}
authelia_config_server_endpoints:
enable_expvars: "{{ authelia_config_server_endpoints_enable_expvars }}"
enable_pprof: "{{ authelia_config_server_endpoints_enable_pprof }}"
authelia_config_server_buffers:
read: "{{ authelia_config_server_buffers_read }}"
write: "{{ authelia_config_server_buffers_write }}"
authelia_config_server_tls:
key: "{{ authelia_config_server_tls_key }}"
certificate: "{{ authelia_config_server_tls_certificate }}"
@ -130,10 +134,11 @@ authelia_config_authentication_backend_ldap:
additional_groups_dn: "{{ authelia_config_authentication_backend_ldap_additional_groups_dn }}"
users_filter: "{{ authelia_config_authentication_backend_ldap_users_filter }}"
groups_filter: "{{ authelia_config_authentication_backend_ldap_groups_filter }}"
group_name_attribute: "{{ authelia_config_authentication_backend_ldap_group_name_attribute }}"
username_attribute: "{{ authelia_config_authentication_backend_ldap_username_attribute }}"
mail_attribute: "{{ authelia_config_authentication_backend_ldap_mail_attribute }}"
display_name_attribute: "{{ authelia_config_authentication_backend_ldap_display_name_attribute }}"
attributes:
username: "{{ authelia_config_authentication_backend_ldap_attributes_username }}"
mail: "{{ authelia_config_authentication_backend_ldap_attributes_mail }}"
display_name: "{{ authelia_config_authentication_backend_ldap_attributes_display_name }}"
group_name: "{{ authelia_config_authentication_backend_ldap_attributes_group_name }}"
user: "{{ authelia_config_authentication_backend_ldap_user }}"
password: "{{ authelia_config_authentication_backend_ldap_password }}"
authelia_config_authentication_backend_file:
@ -172,7 +177,7 @@ authelia_config_session:
secret: "{{ authelia_config_session_secret }}"
expiration: "{{ authelia_config_session_expiration }}"
inactivity: "{{ authelia_config_session_inactivity }}"
remember_me_duration: "{{ authelia_config_session_remember_me_duration }}"
remember_me: "{{ authelia_config_session_remember_me }}"
authelia_config_session_redis: >-2
{{
{

View File

@ -1,7 +1,6 @@
---
ghost_domain: ~
ghost_version: "5.94.1"
ghost_version: "5.96.0"
ghost_user: ghost
ghost_user_group: ghost
ghost_base_path: /opt/ghost

10
roles/ghost/meta/main.yml Normal file
View File

@ -0,0 +1,10 @@
---
allow_duplicates: true
dependencies: []
galaxy_info:
role_name: ghost
description: Ansible role to deploy ghost (https://ghost.org) using docker
galaxy_tags:
- ghost
- blog
- docker

View File

@ -1,6 +1,5 @@
---
gitea_version: "1.22.2"
gitea_version: "1.22.3"
gitea_user: git
gitea_run_user: "{{ gitea_user }}"
gitea_base_path: "/opt/gitea"
@ -11,7 +10,7 @@ gitea_domain: ~
# container config
gitea_container_name: "{{ gitea_user }}"
gitea_contianer_image_server: "docker.io"
gitea_container_image_server: "docker.io"
gitea_container_image_name: "gitea"
gitea_container_image_namespace: gitea
gitea_container_image_fq_name: >-

10
roles/gitea/meta/main.yml Normal file
View File

@ -0,0 +1,10 @@
---
allow_duplicates: true
dependencies: []
galaxy_info:
role_name: gitea
description: Ansible role to deploy gitea using docker
galaxy_tags:
- gitea
- git
- docker

View File

@ -1,7 +1,7 @@
---
- name: Ensure gitea user '{{ gitea_user }}' is present
user:
ansible.builtin.user:
name: "{{ gitea_user }}"
state: "present"
system: false
@ -9,7 +9,7 @@
register: gitea_user_res
- name: Ensure host directories exist
file:
ansible.builtin.file:
path: "{{ item }}"
owner: "{{ gitea_user_res.uid }}"
group: "{{ gitea_user_res.group }}"
@ -19,7 +19,7 @@
- "{{ gitea_data_path }}"
- name: Ensure .ssh folder for gitea user exists
file:
ansible.builtin.file:
path: "/home/{{ gitea_user }}/.ssh"
state: directory
owner: "{{ gitea_user_res.uid }}"
@ -38,7 +38,7 @@
register: gitea_user_ssh_key
- name: Create forwarding script
copy:
ansible.builtin.copy:
dest: "/usr/local/bin/gitea"
owner: "{{ gitea_user_res.uid }}"
group: "{{ gitea_user_res.group }}"
@ -47,7 +47,7 @@
ssh -p {{ gitea_public_ssh_server_port }} -o StrictHostKeyChecking=no {{ gitea_run_user }}@127.0.0.1 -i /home/{{ gitea_user }}/.ssh/id_ssh_ed25519 "SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $0 $@"
- name: Add host pubkey to git users authorized_keys file
lineinfile:
ansible.builtin.lineinfile:
path: "/home/{{ gitea_user }}/.ssh/authorized_keys"
line: "{{ gitea_user_ssh_key.public_key }} Gitea:Host2Container"
state: present
@ -77,7 +77,7 @@
state: "{{ gitea_container_state }}"
- name: Ensure given configuration is set in the config file
ini_file:
ansible.builtin.ini_file:
path: "{{ gitea_data_path }}/gitea/conf/app.ini"
section: "{{ section }}"
option: "{{ option }}"

21
roles/hedgedoc/README.md Normal file
View File

@ -0,0 +1,21 @@
# `finallycoffee.services.hedgedoc` ansible role
Role to deploy and configure hedgedoc using `docker` or `podman`.
To configure hedgedoc, set either the config as complex data
directly in `hedgedoc_config` or use the flattened variables
from the `hedgedoc_config_*` prefix (see
[defaults/main/config.yml](defaults/main/config.yml)).
To remove hedgedoc, set `hedgedoc_state: absent`. Note that this
will delete all data directories aswell, removing any traces this
role created on the target (except database contents).
# Required configuration
- `hedgedoc_config_domain` - Domain of the hedgedoc instance
- `hedgedoc_config_session_secret` - session secret for hedgedoc
## Deployment methods
To set the desired deployment method, set `hedgedoc_deployment_method` to a
supported deployment methods (see [vars/main.yml](vars/main.yml#5)).

View File

@ -0,0 +1,52 @@
---
hedgedoc_config_domain: ~
hedgedoc_config_log_level: "info"
hedgedoc_config_session_secret: ~
hedgedoc_config_protocol_use_ssl: true
hedgedoc_config_hsts_enable: true
hedgedoc_config_csp_enable: true
hedgedoc_config_cookie_policy: 'lax'
hedgedoc_config_allow_free_url: true
hedgedoc_config_allow_email_register: false
hedgedoc_config_allow_anonymous: true
hedgedoc_config_allow_gravatar: true
hedgedoc_config_require_free_url_authentication: true
hedgedoc_config_default_permission: 'full'
hedgedoc_config_db_username: hedgedoc
hedgedoc_config_db_password: ~
hedgedoc_config_db_database: hedgedoc
hedgedoc_config_db_host: localhost
hedgedoc_config_db_port: 5432
hedgedoc_config_db_dialect: postgres
hedgedoc_config_database:
username: "{{ hedgedoc_config_db_username }}"
password: "{{ hedgedoc_config_db_password }}"
database: "{{ hedgedoc_config_db_database }}"
host: "{{ hedgedoc_config_db_host }}"
port: "{{ hedgedoc_config_db_port | int }}"
dialect: "{{ hedgedoc_config_db_dialect }}"
hedgedoc_config_base:
production:
domain: "{{ hedgedoc_config_domain }}"
loglevel: "{{ hedgedoc_config_log_level }}"
sessionSecret: "{{ hedgedoc_config_session_secret }}"
protocolUseSSL: "{{ hedgedoc_config_protocol_use_ssl }}"
cookiePolicy: "{{ hedgedoc_config_cookie_policy }}"
allowFreeURL: "{{ hedgedoc_config_allow_free_url }}"
allowAnonymous: "{{ hedgedoc_config_allow_anonymous }}"
allowEmailRegister: "{{ hedgedoc_config_allow_email_register }}"
allowGravatar: "{{ hedgedoc_config_allow_gravatar }}"
requireFreeURLAuthentication: >-2
{{ hedgedoc_config_require_free_url_authentication }}
defaultPermission: "{{ hedgedoc_config_default_permission }}"
hsts:
enable: "{{ hedgedoc_config_hsts_enable }}"
csp:
enable: "{{ hedgedoc_config_csp_enable }}"
db: "{{ hedgedoc_config_database }}"
hedgedoc_config: ~
hedgedoc_full_config: >-2
{{ hedgedoc_config_base | default({}, true)
| combine(hedgedoc_config | default({}, true), recursive=True) }}

View File

@ -0,0 +1,57 @@
---
hedgedoc_container_image_registry: quay.io
hedgedoc_container_image_namespace: hedgedoc
hedgedoc_container_image_name: hedgedoc
hedgedoc_container_image_flavour: alpine
hedgedoc_container_image_tag: ~
hedgedoc_container_image: >-2
{{
([
hedgedoc_container_image_registry,
hedgedoc_container_image_namespace | default([], true),
hedgedoc_container_image_name,
] | flatten | join('/'))
+ ':'
+ hedgedoc_container_image_tag | default(
hedgedoc_version + (
((hedgedoc_container_image_flavour is string)
and (hedgedoc_container_image_flavour | length > 0))
| ternary('-' +
hedgedoc_container_image_flavour | default('', true),
''
)
),
true
)
}}
hedgedoc_container_image_source: pull
hedgedoc_container_name: hedgedoc
hedgedoc_container_state: >-2
{{ (hedgedoc_state == 'present') | ternary('started', 'absent') }}
hedgedoc_container_config_file: "/hedgedoc/config.json"
hedgedoc_container_upload_path: "/hedgedoc/public/uploads"
hedgedoc_container_env: ~
hedgedoc_container_user: >-2
{{ hedgedoc_run_user_id }}:{{ hedgedoc_run_group_id }}
hedgedoc_container_ports: ~
hedgedoc_container_networks: ~
hedgedoc_container_etc_hosts: ~
hedgedoc_container_base_volumes:
- "{{ hedgedoc_config_file }}:{{ hedgedoc_container_config_file }}:ro"
- "{{ hedgedoc_uploads_path }}:{{ hedgedoc_container_upload_path }}:rw"
hedgedoc_container_volumes: ~
hedgedoc_container_all_volumes: >-2
{{ hedgedoc_container_base_volumes | default([], true)
+ hedgedoc_container_volumes | default([], true) }}
hedgedoc_container_base_labels:
version: "{{ hedgedoc_container_tag | default(hedgedoc_version, true) }}"
hedgedoc_container_labels: ~
hedgedoc_container_network_mode: ~
hedgedoc_container_all_labels: >-2
{{ hedgedoc_container_base_labels | default({}, true)
| combine(hedgedoc_container_labels | default({}, true)) }}
hedgedoc_container_restart_policy: >-2
{{ (hedgedoc_deployment_method === 'docker')
| ternary('unless-stopped', 'on-failure') }}

View File

@ -0,0 +1,9 @@
---
hedgedoc_user: hedgedoc
hedgedoc_version: "1.10.0"
hedgedoc_state: present
hedgedoc_deployment_method: docker
hedgedoc_config_file: "/etc/hedgedoc/config.json"
hedgedoc_uploads_path: "/var/lib/hedgedoc-uploads"

View File

@ -0,0 +1,5 @@
---
hedgedoc_run_user_id: >-2
{{ hedgedoc_user_info.uid | default(hedgedoc_user) }}
hedgedoc_run_group_id: >-2
{{ hedgedoc_user_info.group | default(hedgedoc_user) }}

View File

@ -0,0 +1,12 @@
---
allow_duplicates: true
dependencies: []
galaxy_info:
role_name: hedgedoc
description: >-2
Deploy hedgedoc, a collaborative markdown editor, using docker
galaxy_tags:
- hedgedoc
- markdown
- collaboration
- docker

View File

@ -0,0 +1,23 @@
---
- name: Check for valid state
ansible.builtin.fail:
msg: >-2
Unsupported state '{{ hedgedoc_state }}'. Supported
states are {{ hedgedoc_states | join(', ') }}.
when: hedgedoc_state not in hedgedoc_states
- name: Check for valid deployment method
ansible.builtin.fail:
msg: >-2
Deployment method '{{ hedgedoc_deployment_method }}'
is not supported. Supported are:
{{ hedgedoc_deployment_methods | join(', ') }}
when: hedgedoc_deployment_method not in hedgedoc_deployment_methods
- name: Ensure required variables are given
ansible.builtin.fail:
msg: "Required variable '{{ item }}' is undefined!"
loop: "{{ hedgedoc_required_arguments }}"
when: >-2
item not in hostvars[inventory_hostname]
or hostvars[inventory_hostname][item] | length == 0

View File

@ -0,0 +1,31 @@
---
- name: Ensure container image '{{ hedgedoc_container_image }}' is {{ hedgedoc_state }}
community.docker.docker_image:
name: "{{ hedgedoc_container_image }}"
state: "{{ hedgedoc_state }}"
source: "{{ hedgedoc_container_image_source }}"
force_source: >-2
{{ hedgedoc_container_force_source | default(
hedgedoc_container_image_tag | default(false, true), true) }}
register: hedgedoc_container_image_info
until: hedgedoc_container_image_info is success
retries: 5
delay: 3
- name: Ensure container '{{ hedgedoc_container_name }}' is {{ hedgedoc_container_state }}
community.docker.docker_container:
name: "{{ hedgedoc_container_name }}"
image: "{{ hedgedoc_container_image }}"
env: "{{ hedgedoc_container_env | default(omit, true) }}"
user: "{{ hedgedoc_container_user | default(omit, true) }}"
ports: "{{ hedgedoc_container_ports | default(omit, true) }}"
labels: "{{ hedgedoc_container_all_labels }}"
volumes: "{{ hedgedoc_container_all_volumes }}"
etc_hosts: "{{ hedgedoc_container_etc_hosts | default(omit, true) }}"
dns_servers: >-2
{{ hedgedoc_container_dns_servers | default(omit, true) }}
network_mode: >-2
{{ hedgedoc_container_network_mode | default(omit, true) }}
restart_policy: >-2
{{ hedgedoc_container_restart_policy | default(omit, true) }}
state: "{{ hedgedoc_container_state }}"

View File

@ -0,0 +1,21 @@
---
- name: Check preconditions
ansible.builtin.include_tasks:
file: "check.yml"
- name: Ensure user '{{ hedgedoc_user }}' is {{ hedgedoc_state }}
ansible.builtin.user:
name: "{{ hedgedoc_user }}"
state: "{{ hedgedoc_state }}"
system: "{{ hedgedoc_user_system | default(true, false) }}"
register: hedgedoc_user_info
- name: Ensure configuration file '{{ hedgedoc_config_file }}' is {{ hedgedoc_state }}
ansible.builtin.copy:
dest: "{{ hedgedoc_config_file }}"
content: "{{ hedgedoc_full_config | to_nice_json }}"
when: hedgedoc_state == 'present'
- name: Ensure hedgedoc is deployed using {{ hedgedoc_deployment_method }}
ansible.builtin.include_tasks:
file: "deploy-{{ hedgedoc_deployment_method }}.yml"

View File

@ -0,0 +1,11 @@
---
hedgedoc_states:
- present
- absent
hedgedoc_deployment_methods:
- docker
- podman
hedgedoc_required_arguments:
- hedgedoc_config_domain
- hedgedoc_config_session_secret

View File

@ -1,7 +1,7 @@
---
jellyfin_user: jellyfin
jellyfin_version: 10.9.11
jellyfin_state: present
jellyfin_base_path: /opt/jellyfin
jellyfin_config_path: "{{ jellyfin_base_path }}/config"
@ -12,7 +12,11 @@ jellyfin_media_volumes: []
jellyfin_container_name: jellyfin
jellyfin_container_image_name: "docker.io/jellyfin/jellyfin"
jellyfin_container_image_tag: ~
jellyfin_container_image_ref: "{{ jellyfin_container_image_name }}:{{ jellyfin_container_image_tag | default(jellyfin_version, true) }}"
jellyfin_container_image_ref: >-2
{{ jellyfin_container_image_name }}:{{ jellyfin_container_image_tag | default(jellyfin_version, true) }}
jellyfin_container_image_source: pull
jellyfin_container_state: >-2
{{ (jellyfin_state == 'present') | ternary('started', 'absent') }}
jellyfin_container_network_mode: host
jellyfin_container_networks: ~
jellyfin_container_volumes: "{{ jellyfin_container_base_volumes + jellyfin_media_volumes }}"

View File

@ -0,0 +1,10 @@
---
allow_duplicates: true
dependencies: []
galaxy_info:
role_name: jellyfin
description: Ansible role to deploy jellyfin using docker
galaxy_tags:
- jellyfin
- streaming
- docker

View File

@ -1,34 +1,41 @@
---
- name: Check if state is valid
ansible.builtin.fail:
msg: >-2
Unsupported state '{{ jellyfin_state }}'. Supported
states are {{ jellyfin_states | join(', ') }}.
when: jellyfin_state not in jellyfin_states
- name: Ensure user '{{ jellyfin_user }}' for jellyfin is created
user:
- name: Ensure jellyfin user '{{ jellyfin_user }}' is {{ jellyfin_state }}
ansible.builtin.user:
name: "{{ jellyfin_user }}"
state: present
system: yes
state: "{{ jellyfin_state }}"
system: "{{ jellyfin_user_system | default(true, true) }}"
register: jellyfin_user_info
- name: Ensure host directories for jellyfin exist
file:
- name: Ensure host directories for jellyfin are {{ jellyfin_state }}
ansible.builtin.file:
path: "{{ item.path }}"
state: directory
state: >-2
{{ (jellyfin_state == 'present') | ternary('directory', 'absent') }}
owner: "{{ item.owner | default(jellyfin_uid) }}"
group: "{{ item.group | default(jellyfin_gid) }}"
mode: "{{ item.mode }}"
loop: "{{ jellyfin_host_directories }}"
- name: Ensure container image for jellyfin is available
docker_image:
- name: Ensure container image '{{ jellyfin_container_image_ref }}' is {{ jellyfin_state }}
community.docker.docker_image:
name: "{{ jellyfin_container_image_ref }}"
state: present
source: pull
state: "{{ jellyfin_state }}"
source: "{{ jellyfin_container_image_source }}"
force_source: "{{ jellyfin_container_image_tag | default(false, true) }}"
register: jellyfin_container_image_pull_result
until: jellyfin_container_image_pull_result is succeeded
retries: 5
delay: 3
- name: Ensure container '{{ jellyfin_container_name }}' is running
docker_container:
- name: Ensure container '{{ jellyfin_container_name }}' is {{ jellyfin_container_state }}
community.docker.docker_container:
name: "{{ jellyfin_container_name }}"
image: "{{ jellyfin_container_image_ref }}"
user: "{{ jellyfin_uid }}:{{ jellyfin_gid }}"
@ -37,4 +44,4 @@
networks: "{{ jellyfin_container_networks | default(omit, True) }}"
network_mode: "{{ jellyfin_container_network_mode }}"
restart_policy: "{{ jellyfin_container_restart_policy }}"
state: started
state: "{{ jellyfin_container_state }}"

View File

@ -1,4 +1,7 @@
---
jellyfin_states:
- present
- absent
jellyfin_container_base_volumes:
- "{{ jellyfin_config_path }}:/config:z"

15
roles/snipe_it/README.md Normal file
View File

@ -0,0 +1,15 @@
# `finallycoffee.services.snipe_it` ansible role
[Snipe-IT](https://snipeitapp.com/) is an open-source asset management with
a powerful JSON-REST API. This ansible role deploys and configures Snipe-IT.
## Requirements
Snipe-IT requires a MySQL-Database like MariaDB and a working email service
for sending email. For installing and configuring MariaDB, see
[`finallycoffee.base.mariadb`](https://galaxy.ansible.com/ui/repo/published/finallycoffee/base/content/role/mariadb/).
## Configuration
- `snipe_it_config_app_url`
- `snipe_it_config_app_key`

View File

@ -0,0 +1,133 @@
---
snipe_it_config_app_version: "v{{ snipe_it_version }}"
snipe_it_config_app_port: 8000
snipe_it_config_app_env: "production"
snipe_it_config_app_debug: false
snipe_it_config_app_key: ~
snipe_it_config_app_url: "http://localhost:{{ snipe_it_config_app_port }}"
snipe_it_config_app_timezone: UTC
snipe_it_config_app_locale: en-US
snipe_it_config_app_locked: false
snipe_it_config_app_cipher: "AES-256-GCM"
snipe_it_config_app_force_tls: false
snipe_it_config_app_trusted_proxies:
- '192.168.0.0/16'
- '172.16.0.0/12'
- '10.0.0.0/8'
snipe_it_config_db_connection: mysql
snipe_it_config_db_host: localhost
snipe_it_config_db_port: "3306"
snipe_it_config_db_database: snipeit
snipe_it_config_db_username: snipeit
snipe_it_config_db_password: ~
snipe_it_config_db_prefix: ~
snipe_it_config_db_dump_path: /usr/bin/
snipe_it_config_db_charset: utf8mb4
snipe_it_config_db_collation: utf8mb4_unicode_ci
snipe_it_config_db_ssl: false
snipe_it_config_db_ssl_is_paas: false
snipe_it_config_db_ssl_key_path: ~
snipe_it_config_db_ssl_cert_path: ~
snipe_it_config_db_ssl_ca_path: ~
snipe_it_config_db_ssl_cipher: ~
snipe_it_config_db_ssl_verify_server: ~
snipe_it_config_mail_mailer: smtp
snipe_it_config_mail_host: ~
snipe_it_config_mail_port:
snipe_it_config_mail_username: ~
snipe_it_config_mail_password: ~
snipe_it_config_mail_tls_verify_peer: true
snipe_it_config_mail_from_addr: ~
snipe_it_config_mail_from_name: ~
snipe_it_config_mail_replyto_addr: "{{ snipe_it_config_mail_from_addr }}"
snipe_it_config_mail_replyto_name: "{{ snipe_it_config_mail_from_name }}"
snipe_it_config_mail_auto_embed_method: attachment
snipe_it_config_mail_backup_notification_driver: ~
snipe_it_config_mail_backup_notification_address: ~
snipe_it_config_private_filesystem_disk: >-2
{{ snipe_it_data_directory }}/uploads/private
snipe_it_config_public_filesystem_disk: >-2
{{ snipe_it_data_directory }}/uploads/public
snipe_it_config_allow_backup_delete: false
snipe_it_config_allow_data_purge: false
snipe_it_config_image_lib: 'gd'
snipe_it_config_log_channel: 'stderr'
snipe_it_config_log_max_days: 10
snipe_it_config_cookie_name: ".snipeit_session"
snipe_it_config_cookie_domain: "{{ snipe_it_domain }}"
snipe_it_config_secure_cookies: true
snipe_it_config_session_driver: file
snipe_it_config_session_lifetime: 12000
snipe_it_config_cache_driver: file
snipe_it_config_cache_prefix: snipeit
snipe_it_config_queue_driver: file
snipe_it_base_config:
APP_VERSION: "{{ snipe_it_config_app_version }}"
APP_PORT: "{{ snipe_it_config_app_port }}"
APP_ENV: "{{ snipe_it_config_app_env }}"
APP_DEBUG: "{{ snipe_it_config_app_debug }}"
APP_KEY: "{{ snipe_it_config_app_key }}"
APP_URL: "{{ snipe_it_config_app_url }}"
APP_TIMEZONE: "{{ snipe_it_config_app_timezone }}"
APP_LOCALE: "{{ snipe_it_config_app_locale }}"
APP_LOCKED: "{{ snipe_it_config_app_locked }}"
APP_CIPHER: "{{ snipe_it_config_app_cipher }}"
APP_FORCE_TLS: "{{ snipe_it_config_app_force_tls }}"
APP_TRUSTED_PROXIES: "{{ snipe_it_config_app_trusted_proxies | join(',') }}"
DB_CONNECTION: "{{ snipe_it_config_db_connection }}"
DB_HOST: "{{ snipe_it_config_db_host }}"
DB_PORT: "{{ snipe_it_config_db_port }}"
DB_DATABASE: "{{ snipe_it_config_db_database }}"
DB_USERNAME: "{{ snipe_it_config_mail_username }}"
DB_PASSWORD: "{{ snipe_it_config_db_password }}"
DB_PREFIX: "{{ snipe_it_config_db_prefix }}"
DB_DUMP_PATH: "{{ snipe_it_config_db_dump_path }}"
DB_CHARSET: "{{ snipe_it_config_db_charset }}"
DB_COLLATION: "{{ snipe_it_config_db_collation }}"
DB_SSL: "{{ snipe_it_config_db_ssl }}"
DB_SSL_IS_PAAS: "{{ snipe_it_config_db_ssl_is_paas }}"
DB_SSL_KEY_PATH: "{{ snipe_it_config_db_ssl_key_path }}"
DB_SSL_CERT_PATH: "{{ snipe_it_config_db_ssl_cert_path }}"
DB_SSL_CA_PATH: "{{ snipe_it_config_db_ssl_ca_path }}"
DB_SSL_CIPHER: "{{ snipe_it_config_db_ssl_cipher }}"
DB_SSL_VERIFY_SERVER: "{{ snipe_it_config_db_ssl_verify_server }}"
MAIL_MAILER: "{{ snipe_it_config_mail_mailer }}"
MAIL_HOST: "{{ snipe_it_config_mail_host }}"
MAIL_PORT: "{{ snipe_it_config_mail_port }}"
MAIL_USERNAME: "{{ snipe_it_config_mail_username }}"
MAIL_PASSWORD: "{{ snipe_it_config_mail_password }}"
MAIL_TLS_VERIFY_PEER: "{{ snipe_it_config_mail_tls_verify_peer }}"
MAIL_FROM_ADDR: "{{ snipe_it_config_mail_from_addr }}"
MAIL_FROM_NAME: "{{ snipe_it_config_mail_from_name }}"
MAIL_REPLYTO_ADDR: "{{ snipe_it_config_mail_replyto_addr }}"
MAIL_REPLYTO_NAME: "{{ snipe_it_config_mail_replyto_name }}"
MAIL_AUTO_EMBED_METHOD: "{{ snipe_it_config_mail_auto_embed_method }}"
MAIL_BACKUP_NOTIFICATION_DRIVER: "{{ snipe_it_config_mail_backup_notification_driver }}"
MAIL_BACKUP_NOTIFICATION_ADDRESS: "{{ snipe_it_config_mail_backup_notification_address }}"
SESSION_DRIVER: "{{ snipe_it_config_session_driver }}"
SESSION_LIFETIME: "{{ snipe_it_config_session_lifetime }}"
CACHE_DRIVER: "{{ snipe_it_config_cache_driver }}"
CACHE_PREFIX: "{{ snipe_it_config_cache_prefix }}"
QUEUE_DRIVER: "{{ snipe_it_config_queue_driver }}"
PRIVATE_FILESYSTEM_DISK: "{{ snipe_it_config_private_filesystem_disk }}"
PUBLIC_FILESYSTEM_DISK: "{{ snipe_it_config_public_filesystem_disk }}"
ALLOW_BACKUP_DELETE: "{{ snipe_it_config_allow_backup_delete }}"
ALLOW_DATA_PURGE: "{{ snipe_it_config_allow_data_purge }}"
IMAGE_LIB: "{{ snipe_it_config_image_lib }}"
LOG_CHANNEL: "{{ snipe_it_config_log_channel }}"
LOG_MAX_DAYS: "{{ snipe_it_config_log_max_days }}"
COOKIE_NAME: "{{ snipe_it_config_cookie_name }}"
COOKIE_DOMAIN: "{{ snipe_it_config_cookie_domain }}"
SECURE_COOKIES: "{{ snipe_it_config_secure_cookies }}"
snipe_it_config: ~
snipe_it_merged_config: >-2
{{ snipe_it_base_config | default({}, true)
| combine(snipe_it_config | default({}, true), recursive=True) }}

View File

@ -0,0 +1,33 @@
---
snipe_it_container_container_image_registry: docker.io
snipe_it_container_container_image_namespace: snipe
snipe_it_container_container_image_name: 'snipe-it'
snipe_it_container_container_image_tag: ~
snipe_it_container_container_image_flavour: alpine
snipe_it_container_container_image_source: pull
snipe_it_container_container_image_force_source: >-2
{{ snipe_it_container_container_image_tag | default(false, true) | bool }}
snipe_it_container_container_image: >-2
{{
([
snipe_it_container_container_image_registry | default([], true),
snipe_it_container_container_image_namespace | default([], true),
snipe_it_container_container_image_name,
] | flatten | join('/'))
+ ':'
+ (vaultwarden_container_image_tag | default(
'v' + vaultwarden_version + (
((snipe_it_container_container_image_flavour is string)
and (snipe_it_container_container_image_flavour | length > 0))
| ternary(
'-' + snipe_it_container_container_image_flavour | default('', true),
''
)
),
true
))
}}
snipe_it_container_env_file: "{{ snipe_it_env_file }}"
snipe_it_container_user: ~
snipe_it_container_ #TODO

View File

@ -0,0 +1,8 @@
---
snipe_it_user: snipeit
snipe_it_version: "7.0.13"
snipe_it_state: present
snipe_it_deployment_method: docker
snipe_it_env_file: /etc/snipeit/env
snipe_it_data_directory: /var/lib/snipeit

View File

@ -0,0 +1,5 @@
---
snipe_it_run_user_id: >-2
{{ snipe_it_user_info.uid | default(snipe_it_user) }}
snipe_it_run_group_id: >-2
{{ snipe_it_user_info.group | default(snipe_it_user) }}

View File

@ -0,0 +1,12 @@
---
allow_duplicates: true
dependencies: []
galaxy_info:
role_name: snipe_it
description: >-2
Deploy Snipe-IT, an open-source asset / license management system with
powerful JSON REST API
galaxy_tags:
- snipeit
- asset-management
- docker

View File

@ -0,0 +1,14 @@
---
- name: Ensure state is valid
ansible.builtin.fail:
msg: >-2
Unsupported state '{{ snipe_it_state }}'!
Supported states are {{ snipe_it_states | join(', ') }}.
when: snipe_it_state is not in snipe_it_states
- name: Ensure deployment method is valid
ansible.builtin.fail:
msg: >-2
Unsupported deployment_method '{{ snipe_it_deployment_method }}'!
Supported values are {{ snipe_it_deployment_methods | join(', ') }}.
when: snipe_it_deployment_method is not in snipe_it_deployment_methods

View File

@ -0,0 +1,18 @@
---
- name: Ensure container image '{{ snipe_it_container_image }}' is {{ snipe_it_state }}
community.docker.docker_image:
name: "{{ snipe_it_container_image }}"
state: "{{ snipe_it_state }}"
source: "{{ snipe_it_container_image_source }}"
force_source: "{{ snipe_it_container_image_force_source }}"
register: snipe_it_container_image_info
until: snipe_it_container_image_info is success
retries: 5
delay: 3
- name: Ensure container '{{ snipe_it_container_name }}' is {{ snipe_it_container_state }}
community.docker.docker_container:
name: "{{ snipe_it_container_name }}"
image: "{{ snipe_it_container_image }}"
# more args
state: "{{ snipe_it_container_state }}"

View File

@ -0,0 +1,59 @@
---
- name: Check preconditions
ansible.builtin.include_tasks:
file: "check.yml"
- name: Ensure snipe-it user '{{ snipe_it_user }}' is {{ snipe_it_state }}
ansible.builtin.user:
name: "{{ snipe_it_user }}"
state: "{{ snipe_it_state }}"
system: "{{ snipe_it_user_system | default(true, true) }}"
create_home: "{{ snipe_it_user_create_home | default(false, true) }}"
groups: "{{ snipe_it_user_groups | default(omit, true) }}"
append: >-2
{{
snipe_it_user_groups_append | default(
snipe_it_user_groups | default([], true) | length > 0,
true,
)
}}
register: snipe_it_user_info
- name: Ensure snipe-it environment file is {{ snipe_it_state }}
ansible.builtin.file:
path: "{{ snipe_it_config_file }}"
state: "{{ snipe_it_state }}"
when: snipe_it_state == 'absent'
- name: Ensure snipe-it config directory is {{ snipe_it_state }}
ansible.builtin.file:
path: "{{ snipe_it_config_file | dirname }}"
state: "{{ (snipe_it_state == 'present') | ternary('directory', 'absent') }}"
owner: "{{ snipe_it_run_user_id }}"
group: "{{ snipe_it_run_group_id }}"
mode: "0755"
when: snipe_it_state == 'present'
- name: Ensure snipe-it data directory '{{ snipe_it_data_directory }}' is {{ snipe_it_state }}
ansible.builtin.file:
path: "{{ snipe_it_data_directory }}"
state: "{{ (snipe_it_state == 'present') | ternary('directory', 'absent') }}"
owner: "{{ snipe_it_run_user_id }}"
group: "{{ snipe_it_run_group_id }}"
mode: "0755"
- name: Ensure snipe-it environment file is templated
ansible.builtin.copy:
content: |+2
{% for entry in snipe_it_merged_config | dict2items %}
{{ entry.key }}={{ entry.value }}
{% endfor %}
path: "{{ snipe_it_config_file }}"
owner: "{{ snipe_it_run_user_id }}"
group: "{{ snipe_it_run_group_id }}"
mode: "0640"
when: snipe_it_state == 'present'
- name: Deploy using {{ snipe_it_deployment_method }}
ansible.builtin.include_tasks:
file: "deploy-{{ snipe_it_deployment_method }}.yml"

View File

@ -0,0 +1,6 @@
---
snipe_it_states:
- present
- absent
snipe_it_deployment_methods:
- docker

View File

@ -0,0 +1,54 @@
# `finallycoffee.services.vaultwarden` ansible role
Vaultwarden is an unofficial (not associated with Bitwarden) bitwarden API compatible
server backend, formally called `bitwarden_rs`, written in rust.
This ansible role can deploy and configure `vaultwarden`, and supports removing
itself using `vaultwarden_state: absent` (Warning: It does not ask for confirmation,
and will remove all user data when instructed to remove it).
## Configuration
To use this role, the following variables need to be populated:
- `vaultwarden_config_domain` - always. Changing this will lead to two-factor not working for two-factor methods registered in the past.
- `vaultwarden_config_admin_token` - if `vaultwarden_config_disable_admin_token` is `false`.
Setting other configuration values for vaultwarden can be done using role-provided flattened keys in the
`vaultwarden_config_*` namespace (see [`defaults/main/config.yml`](defaults/main/config.yml) for available variables),
or by setting the configuration directly in the same structure as the `config.json` would be in `vaultwarden_config`.
### Email
Configure mailing by first enabling SMTP using `vaultwarden_config_enable_smtp: true`,
then configure your email server like this:
```yaml
vaultwarden_config:
smtp_host: "mail.example.com"
smtp_explicit_tls: true
smtp_port: 465
smtp_from: "noreply+vaultwarden@example.com"
smtp_from_name: "'Example.com Vaultwarden instance' <noreply+vaultwarden@example.com>"
smtp_username: vaultwarden@example.com
smtp_password: i_hope_i_will_be_a_strong_one!
helo_name: "{{ vaultwarden_config_domain }}"
```
### 2FA via email
To enable email-based two-factor-authentication, set `vaultwarden_config_enable_email_2fa: true`
and optionally set the following configuration:
```yaml
vaultwarden_config:
email_token_size: 8
email_expiration_time: 300 # 300 seconds = 5min
email_attempts_limit: 3
```
### Feature flags
To enable more authentication methods, toggles are provided in
[`vaultwarden_config_enable_*`](defaults/main/config.yml#L18).
It is genereally recommended to simply keep unused methods off.
Per default, 'Sends' are allowed.

View File

@ -0,0 +1,68 @@
---
# Required configuration
vaultwarden_config_domain: ~
vaultwarden_config_admin_token: ~
# Invitations and signups
vaultwarden_config_invitations_allowed: false
vaultwarden_config_invitation_org_name: ~
vaultwarden_config_signups_allowed: false
vaultwarden_config_signups_verify: true
vaultwarden_config_signups_verify_resend_time: 3600
vaultwarden_config_signups_verify_resend_limit: 5
# Entry preview icons
vaultwarden_config_disable_icon_download: true
vaultwarden_config_icon_cache_ttl: 604800 # 7 days
vaultwarden_config_icon_cache_negttl: 259200 # 3 days
vaultwarden_config_icon_download_timeout: 30 # seconds
vaultwarden_config_icon_blacklist_non_global_ips: true
# Features
vaultwarden_config_sends_allowed: true
vaultwarden_config_enable_yubico: false
vaultwarden_config_enable_duo: false
vaultwarden_config_enable_smtp: false
vaultwarden_config_enable_email_2fa: false
# Security
vaultwarden_config_password_iterations: 100000
vaultwarden_config_show_password_hint: false
vaultwarden_config_disable_2fa_remember: false
vaultwarden_config_disable_admin_token: true
vaultwarden_config_require_device_email: false
vaultwarden_config_authenticator_disable_time_drift: true
# Other
vaultwarden_config_log_timestamp_format: "%Y-%m-%d %H:%M:%S.%3f"
vaultwarden_config_ip_header: "X-Real-IP"
vaultwarden_config_reload_templates: false
vaultwarden_base_config:
domain: "{{ vaultwarden_config_domain }}"
admin_token: "{{ vaultwarden_config_admin_token }}"
invitations_allowed: "{{ vaultwarden_config_invitations_allowed }}"
invitation_org_name: "{{ vaultwarden_config_invitation_org_name | default('', true) }}"
signups_allowed: "{{ vaultwarden_config_signups_allowed }}"
signups_verify: "{{ vaultwarden_config_signups_verify }}"
signups_verify_resend_time: "{{ vaultwarden_config_signups_verify_resend_time }}"
signups_verify_resend_limit: "{{ vaultwarden_config_signups_verify_resend_limit }}"
disable_icon_download: "{{ vaultwarden_config_disable_icon_download }}"
icon_cache_ttl: "{{ vaultwarden_config_icon_cache_ttl }}"
icon_cache_negttl: "{{ vaultwarden_config_icon_cache_negttl }}"
icon_download_timeout: "{{ vaultwarden_config_icon_download_timeout }}"
icon_blacklist_non_global_ips: "{{ vaultwarden_config_icon_blacklist_non_global_ips }}"
password_iterations: "{{ vaultwarden_config_password_iterations }}"
show_password_hint: "{{ vaultwarden_config_show_password_hint }}"
disable_2fa_remember: "{{ vaultwarden_config_disable_2fa_remember }}"
disable_admin_token: "{{ vaultwarden_config_disable_admin_token }}"
require_device_email: "{{ vaultwarden_config_require_device_email }}"
authenticator_disable_time_drift: "{{ vaultwarden_config_authenticator_disable_time_drift }}"
ip_header: "{{ vaultwarden_config_ip_header }}"
log_timestamp_format: "{{ vaultwarden_config_log_timestamp_format }}"
reload_templates: "{{ vaultwarden_config_reload_templates }}"
sends_allowed: "{{ vaultwarden_config_sends_allowed }}"
_enable_yubico: "{{ vaultwarden_config_enable_yubico }}"
_enable_duo: "{{ vaultwarden_config_enable_duo }}"
_enable_smtp: "{{ vaultwarden_config_enable_smtp }}"
_enable_email_2fa: "{{ vaultwarden_config_enable_email_2fa }}"
vaultwarden_config: ~
vaultwarden_merged_config: >-2
{{ vaultwarden_base_config | default({}, true)
| combine(vaultwarden_config | default({}, true), recursive=true) }}

View File

@ -0,0 +1,50 @@
---
vaultwarden_container_image_registry: docker.io
vaultwarden_container_image_namespace: vaultwarden
vaultwarden_container_image_name: server
vaultwarden_container_image_tag: ~
vaultwarden_container_image_flavour: alpine
vaultwarden_container_image_source: pull
vaultwarden_container_image_force_source: >-2
{{ vaultwarden_container_image_tag | default(false, true) | bool }}
vaultwarden_container_image: >-2
{{
([
vaultwarden_container_image_registry | default([], true),
vaultwarden_container_image_namespace | default([], true),
vaultwarden_container_image_name,
] | flatten | join('/'))
+ ':'
+ (vaultwarden_container_image_tag | default(
vaultwarden_version + (
((vaultwarden_container_image_flavour is string)
and (vaultwarden_container_image_flavour | length > 0))
| ternary(
'-' + vaultwarden_container_image_flavour | default('', true),
''
)
),
true
))
}}
vaultwarden_container_name: vaultwarden
vaultwarden_container_env: ~
vaultwarden_container_user: >-2
{{ vaultwarden_run_user_id }}:{{ vaultwarden_run_group_id }}
vaultwarden_container_ports: ~
vaultwarden_container_labels: ~
vaultwarden_container_networks: ~
vaultwarden_container_etc_hosts: ~
vaultwarden_container_dns_servers: ~
vaultwarden_container_restart_policy: >-2
{{ (vaultwarden_deployment_method == 'docker') | ternary(
'unless-stopped',
'on-failure',
)
}}
vaultwarden_container_state: >-2
{{ (vaultwarden_state == 'present') | ternary('started', 'absent') }}
vaultwarden_container_volumes:
- "{{ vaultwarden_data_directory }}:/data:rw"
- "{{ vaultwarden_config_file }}:/data/config.json:ro"

View File

@ -0,0 +1,10 @@
---
vaultwarden_user: vaultwarden
vaultwarden_version: "1.32.2"
vaultwarden_config_file: "/etc/vaultwarden/config.json"
vaultwarden_config_directory: "{{ vaultwarden_config_file | dirname }}"
vaultwarden_data_directory: "/var/lib/vaultwarden"
vaultwarden_state: present
vaultwarden_deployment_method: docker

View File

@ -0,0 +1,5 @@
---
vaultwarden_run_user_id: >-2
{{ vaultwarden_user_info.uid | default(vaultwarden_user, true) }}
vaultwarden_run_group_id: >-2
{{ vaultwarden_user_info.group | default(vaultwarden_user, true) }}

View File

@ -0,0 +1,9 @@
---
- name: Ensure vaultwarden container '{{ vaultwarden_container_name }}' is restarted
community.docker.docker_container:
name: "{{ vaultwarden_container_name }}"
state: "{{ vaultwarden_container_state }}"
restart: true
listen: vaultwarden-restart
when: vaultwarden_deployment_method == 'docker'
ignore_errors: "{{ ansible_check_mode }}"

View File

@ -0,0 +1,12 @@
---
allow_duplicates: true
dependencies: []
galaxy_info:
role_name: vaultwarden
description: >-2
Deploy vaultwarden, a bitwarden-compatible server backend
galaxy_tags:
- vaultwarden
- bitwarden
- passwordstore
- docker

View File

@ -0,0 +1,22 @@
---
- name: Ensure container image '{{ vaultwarden_container_image }}' is {{ vaultwarden_state }}
community.docker.docker_image:
name: "{{ vaultwarden_container_image }}"
state: "{{ vaultwarden_state }}"
source: "{{ vaultwarden_container_image_source }}"
force_source: "{{ vaultwarden_container_image_force_source }}"
- name: Ensure container '{{ vaultwarden_container_name }}' is {{ vaultwarden_container_state }}
community.docker.docker_container:
name: "{{ vaultwarden_container_name }}"
image: "{{ vaultwarden_container_image }}"
env: "{{ vaultwarden_container_env | default(omit, true) }}"
user: "{{ vaultwarden_container_user | default(omit, true) }}"
ports: "{{ vaultwarden_container_ports | default(omit, true) }}"
labels: "{{ vaultwarden_container_labels | default(omit, true) }}"
volumes: "{{ vaultwarden_container_volumes }}"
networks: "{{ vaultwarden_container_networks | default(omit, true) }}"
etc_hosts: "{{ vaultwarden_container_etc_hosts | default(omit, true) }}"
dns_servers: "{{ vaultwarden_container_dns_servers | default(omit, true) }}"
restart_policy: "{{ vaultwarden_container_restart_policy | default(omit, true) }}"
state: "{{ vaultwarden_container_state | default(omit, true) }}"

View File

@ -0,0 +1,78 @@
---
- name: Ensure state is valid
ansible.builtin.fail:
msg: >-2
Unsupported state '{{ vaultwarden_state }}'!
Supported states are {{ vaultwarden_states | join(', ') }}.
when: vaultwarden_state not in vaultwarden_states
- name: Ensure deployment method is valid
ansible.builtin.fail:
msg: >-2
Unsupported deployment method '{{ vaultwarden_deployment_method }}'!
Supported are {{ vaultwarden_deployment_methods | join(', ') }}.
when: vaultwarden_deployment_method not in vaultwarden_deployment_methods
- name: Ensure required variables are given
ansible.builtin.fail:
msg: "Required variable '{{ var }}' is undefined!"
loop: "{{ vaultwarden_required_variables }}"
loop_control:
loop_var: var
when: >-2
var not in hostvars[inventory_hostname]
or hostvars[inventory_hostname][var] | length == 0
- name: Ensure required variables are given
ansible.builtin.fail:
msg: "Required variable '{{ var.name }}' is undefined!"
loop: "{{ vaultwarden_conditionally_required_variables }}"
loop_control:
loop_var: var
label: "{{ var.name }}"
when: >-2
var.when and (
var.name not in hostvars[inventory_hostname]
or hostvars[inventory_hostname][var.name] | length == 0)
- name: Ensure vaultwarden user '{{ vaultwarden_user }}' is {{ vaultwarden_state }}
ansible.builtin.user:
name: "{{ vaultwarden_user }}"
state: "{{ vaultwarden_state }}"
system: "{{ vaultwarden_user_system | default(true, true) }}"
create_home: "{{ vaultwarden_user_create_home | default(false, true) }}"
groups: "{{ vaultwarden_user_groups | default(omit, true) }}"
append: >-2
{{ vaultwarden_user_append_groups | default(
(vaultwarden_user_groups | default([], true) | length > 0),
true,
) }}
register: vaultwarden_user_info
- name: Ensure base paths are {{ vaultwarden_state }}
ansible.builtin.file:
path: "{{ mount.path }}"
state: "{{ (vaultwarden_state == 'present') | ternary('directory', 'absent') }}"
owner: "{{ mount.owner | default(vaultwarden_run_user_id) }}"
group: "{{ mount.group | default(vaultwarden_run_group_id) }}"
mode: "{{ mount.mode | default('0755', true) }}"
loop:
- path: "{{ vaultwarden_config_directory }}"
- path: "{{ vaultwarden_data_directory }}"
loop_control:
loop_var: mount
label: "{{ mount.path }}"
- name: Ensure vaultwarden config file '{{ vaultwarden_config_file }}' is {{ vaultwarden_state }}
ansible.builtin.copy:
content: "{{ vaultwarden_merged_config | to_nice_json(indent=4) }}"
dest: "{{ vaultwarden_config_file }}"
owner: "{{ vaultwarden_run_user_id }}"
group: "{{ vaultwarden_run_group_id }}"
mode: "0640"
when: vaultwarden_state == 'present'
notify: vaultwarden-restart
- name: Deploy vaultwarden using {{ vaultwarden_deployment_method }}
ansible.builtin.include_tasks:
file: "deploy-{{ vaultwarden_deployment_method }}.yml"

View File

@ -0,0 +1,11 @@
---
vaultwarden_states:
- present
- absent
vaultwarden_deployment_methods:
- docker
vaultwarden_required_variables:
- vaultwarden_config_domain
vaultwarden_conditionally_required_variables:
- name: vaultwarden_config_admin_token
when: "{{ vaultwarden_config_disable_admin_token | default(true, true) | bool }}"

View File

@ -0,0 +1,12 @@
---
allow_duplicates: true
dependencies: []
galaxy_info:
role_name: vouch_proxy
description: Ansible role to deploy vouch_proxy using docker
galaxy_tags:
- vouch_proxy
- oidc
- authentication
- authorization
- docker