Compare commits

..

No commits in common. 'da712ef7b0dbb43c6669ae968668541d4a69a157' and 'b7754cad545b4739c876b621290f723ebec1bfc2' have entirely different histories.

@ -60,7 +60,7 @@
"name": "plugins/modules/portainer_stack.py",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "8f8c5a3fcefa02becec7dad10442e92db1b40dccdd43e297baa273a03f260105",
"chksum_sha256": "e75fa1655aed9c13955315a80aa9a3f0b54ac1bc386697756bb308e0cfe4ecbb",
"format": 1
},
{

@ -23,7 +23,7 @@
"name": "FILES.json",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "df6db8314d203f2365d1ff4253d6d793197067dced93c835a6b88074c18d4921",
"chksum_sha256": "a3d632538c4fb62677f3dceb2b32648f6688932bfa4354ad1ad21ecd1e031a7d",
"format": 1
},
"format": 1

@ -16,8 +16,6 @@ except ImportError:
_query_params_to_string,
)
import yaml
DOCUMENTATION = r"""
---
module: portainer_stack
@ -119,15 +117,17 @@ def _create_stack(client, module, file_contents):
def _update_stack(client, module, stack_id):
target_stack_name = module.params["stack_name"]
contents = _get_stack_contents(module.params)
with open(module.params["docker_compose_file_path"]) as f:
file_contents = f.read()
return client.put(
f"stacks/{stack_id}?&endpointId={client.endpoint}",
body={
"name": target_stack_name,
"stackFileContent": contents,
"stackFileContent": file_contents,
},
)
def handle_state_present(client, module):
result = dict(changed=False, stack_name=module.params["stack_name"])
@ -135,7 +135,8 @@ def handle_state_present(client, module):
stacks = client.get("stacks")
result["stacks"] = stacks
contents = _get_stack_contents(module.params)
with open(module.params["docker_compose_file_path"]) as f:
file_contents = f.read()
target_stack_name = module.params["stack_name"]
for stack in stacks:
@ -145,7 +146,7 @@ def handle_state_present(client, module):
break
if not already_exists:
stack = _create_stack(client, module, contents)
stack = _create_stack(client, module, file_contents)
result["changed"] = True
result["stack_id"] = stack["Id"]
module.exit_json(**result)
@ -157,7 +158,7 @@ def handle_state_present(client, module):
)
result["are_equal"] = (
current_file_contents_resp["StackFileContent"] == contents
current_file_contents_resp["StackFileContent"] == file_contents
)
if result["are_equal"]:
module.exit_json(**result)
@ -190,22 +191,13 @@ def handle_state_absent(client, module):
)
result["changed"] = True
module.exit_json(**result)
def _get_stack_contents(params):
if params.get("docker_compose_file_path"):
with open(params["docker_compose_file_path"]) as f:
return f.read()
if params.get("definition"):
return yaml.dump(params["definition"], indent=4)
raise ValueError("No docker_compose_file_path or definition provided.")
def run_module():
# define available arguments/parameters a user can pass to the module
module_args = dict(
stack_name=dict(type="str", required=True),
docker_compose_file_path=dict(type="str"),
definition=dict(type=dict),
username=dict(type="str", default="admin"),
password=dict(type="str", required=True, no_log=True),
endpoint_id=dict(type="int", required=True),
@ -213,6 +205,11 @@ def run_module():
state=dict(type="str", default="present", choices=["present", "absent"]),
)
required_if = [
# docker compose file is only required if we are ensuring the stack is present.
["state", "present", ("docker_compose_file_path",)],
]
state_fns = {"present": handle_state_present, "absent": handle_state_absent}
# the AnsibleModule object will be our abstraction working with Ansible
@ -221,16 +218,7 @@ def run_module():
# supports check mode
module = AnsibleModule(
argument_spec=module_args,
# required_if = [
# docker compose file is only required if we are ensuring the stack is present.
# ["state", "present", ("docker_compose_file_path",)],
# ],
mutually_exclusive=[
('docker_compose_file_path', 'definition'),
],
required_one_of=[
('docker_compose_file_path', 'definition'),
],
required_if=required_if,
# TODO: support check mode
supports_check_mode=False,
)

@ -45,6 +45,10 @@ external_docker_networks:
ansible_pull_path: /home/{{ homelab_user }}/.local/bin/ansible-pull
portainer_required_files:
- source_file: dashboards/dashy-config.yml
dest_file_name: dashy-config.yml
dest_directory: /etc/config/dashy
handler: restart-dashy
- source_file: olivetin/config.yml
dest_file_name: config.yml
dest_directory: /etc/config/OliveTin
@ -89,6 +93,11 @@ services:
default_network: mariadb_net
image: nextcloud
tag: 27.0
- name: dashboards
template_vars:
dashy: true
dashdot: true
glances: true
- name: nginx-proxy-manager
- name: plex
template_vars:

@ -12,8 +12,22 @@ portainer_required_templates:
portainer_endpoint: 23
services:
- name: bookstack
template_vars:
image: linuxserver/bookstack
tag: 23.06.1
- name: vaultwarden
template_vars:
image: vaultwarden/server
tag: 1.28.1
- name: linkding
- name: pihole
- name: hasteypaste
- name: dashboards
template_vars:
dashy: false
dashdot: true
glances: true
- name: diun
ansible_pull_path: /usr/local/bin/ansible-pull

@ -55,43 +55,13 @@
- role: setup_compose_services
tags: [compose]
- name: Setup and deploy portainer services (snunmu).
hosts: snunmu
- name: Setup and deploy portainer services.
hosts: servers
become: true
tags: [services]
pre_tasks:
- name: Include vault variables.
ansible.builtin.include_vars: '../{{ vault_file }}'
tags: [always]
roles:
- role: portainer_bookstack
- role: portainer_vaultwarden
- role: portainer_dashy
- role: portainer_dashdot
- role: portainer_glances
- name: Setup and deploy portainer services (qnap).
hosts: qnap
become: true
- role: setup_hosted_services
tags: [services]
pre_tasks:
- name: Include vault variables.
ansible.builtin.include_vars: '../{{ vault_file }}'
tags: [always]
roles:
- role: portainer_dashy
- role: portainer_dashdot
- role: portainer_glances
#
#- name: Setup and deploy templated portainer services.
# hosts: servers
# become: true
# pre_tasks:
# - name: Include vault variables.
# ansible.builtin.include_vars: '../{{ vault_file }}'
# tags: [always]
# roles:
# - role: setup_hosted_services
# tags: [services]

@ -8,7 +8,7 @@ roles:
collections:
- name: https://github.com/chatton/ansible-portainer.git
type: git
version: support_definition
version: master
- name: https://github.com/chatton/ansible-docker-backup.git
type: git
version: master

@ -1,7 +1,7 @@
---
- name: Create a gotify message.
- name: Create a gotify message
ansible.builtin.uri:
url: "{{ gotify_base_url }}/message"
url: "{{ gotify_base_url}}/message"
method: POST
headers:
X-Gotify-Key: "{{ gotify_api_token }}"

@ -1,18 +0,0 @@
---
bookstack_image: linuxserver/bookstack
bookstack_tag: 23.06.1
bookstack_backup_enabled: true
bookstack_backup_schedule: "nightly"
bookstack_puid: 1000
bookstack_pgid: 1000
bookstack_db_host: qnap
bookstack_database: bookstackapp
bookstack_db_user: bookstack
bookstack_app_url: https://bookstack.cianhatton.ie
bookstack_expose_port: 6875
bookstack_restart_policy: unless-stopped
bookstack_container_name: bookstack
bookstack_portainer_stack_name: bookstack
bookstack_docker_backup_restore_force: false
bookstack_docker_backup_restore_latest_s3_key: true
bookstack_docker_backup_fail_on_no_s3_backups: false

@ -1,43 +0,0 @@
---
- name: "Bookstack | Restore any missing volumes from S3"
ansible.builtin.include_role:
name: chatton.docker_backup.docker_s3_volume_restore
vars:
docker_backup_restore_force: "{{ bookstack_docker_backup_restore_force }}"
docker_backup_restore_latest_s3_key: "{{ bookstack_docker_backup_restore_latest_s3_key }}"
docker_backup_fail_on_no_s3_backups: "{{ bookstack_docker_backup_fail_on_no_s3_backups }}"
docker_backup_s3_volume:
name: "{{ bookstack_portainer_stack_name }}_config"
- name: "Bookstack | Update Portainer."
chatton.portainer.portainer_stack:
username: admin
password: '{{ portainer.password }}'
base_url: '{{ portainer_base_url }}'
stack_name: '{{ bookstack_portainer_stack_name }}'
endpoint_id: '{{ portainer_endpoint }}'
state: present
definition:
version: "3.1"
services:
bookstack:
labels:
ie.cianhatton.backup.enabled: "{{ bookstack_backup_enabled }}"
ie.cianhatton.backup.schedule: "{{ bookstack_backup_schedule }}"
image: "{{ bookstack_image }}:{{ bookstack_tag }}"
container_name: "{{ bookstack_container_name }}"
environment:
- PUID={{ bookstack_puid }}
- PGID={{ bookstack_pgid }}
- DB_HOST={{ bookstack_db_host }}
- DB_USER={{ bookstack_db_user }}
- DB_PASS={{ bookstack_password }}
- DB_DATABASE={{ bookstack_database }}
- APP_URL={{ bookstack_app_url }}
volumes:
- config:/config
ports:
- "{{ bookstack_expose_port }}:80"
restart: "{{ bookstack_restart_policy }}"
volumes:
config: {}

@ -1,7 +0,0 @@
---
dashdot_image: mauricenino/dashdot
dashdot_tag: latest
dashdot_expose_port: 3010
dashdot_portainer_stack_name: dashdot
dashdot_container_name: dashdot
dashdot_restart_policy: unless-stopped

@ -1,20 +0,0 @@
---
- name: "Dashy | Update Portainer."
chatton.portainer.portainer_stack:
username: admin
password: '{{ portainer.password }}'
base_url: '{{ portainer_base_url }}'
stack_name: '{{ dashdot_portainer_stack_name }}'
endpoint_id: '{{ portainer_endpoint }}'
state: present
definition:
services:
dashdot:
container_name: "{{ dashdot_container_name}}"
image: "{{ dashdot_image }}:{{ dashdot_tag }}"
restart: "{{ dashdot_restart_policy }}"
privileged: true
ports:
- '{{ dashdot_expose_port }}:3001'
volumes:
- /:/mnt/host:ro

@ -1,14 +0,0 @@
---
dashy_image: lissy93/dashy
dashy_tag: 2.1.1
dashy_expose_port: 4000
dashy_portainer_stack_name: dashy
dashy_container_name: dashy
dashy_restart_policy: unless-stopped
dashy_config_dir: /etc/config/dashy
dashy_config_file: dashy-config.yml
# environment variables
dashy_node_env: production
dashy_uid: 1000
dashy_gid: 1000

@ -1,3 +0,0 @@
---
- name: restart-dashy
ansible.builtin.command: docker restart dashy

@ -1,46 +0,0 @@
---
- name: Create config directory.
ansible.builtin.file:
path: '{{ dashy_config_dir }}'
state: directory
mode: '0755'
- name: Create config file.
ansible.builtin.copy:
src: "dashy-config.yml"
dest: '{{ dashy_config_dir }}/{{ dashy_config_file }}'
owner: root
group: root
mode: 0440
notify: restart-dashy
- name: "Dashy | Update Portainer."
chatton.portainer.portainer_stack:
username: admin
password: '{{ portainer.password }}'
base_url: '{{ portainer_base_url }}'
stack_name: '{{ dashy_portainer_stack_name }}'
endpoint_id: '{{ portainer_endpoint }}'
state: present
definition:
version: '3'
services:
dashy:
container_name: "{{ dashy_container_name }}"
image: "{{ dashy_image }}:{{ dashy_tag }}"
volumes:
- "{{ dashy_config_dir}}/{{ dashy_config_file }}:/app/public/conf.yml"
ports:
- "{{ dashy_expose_port}}:80"
environment:
- "NODE_ENV={{ dashy_node_env }}"
- "UID={{ dashy_uid }}"
- "GID={{ dashy_gid }}"
restart: "{{ dashy_restart_policy}}"
# Configure healthchecks
healthcheck:
test: ['CMD', 'node', '/app/services/healthcheck']
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s

@ -1,8 +0,0 @@
---
glances_image: nicolargo/glances
glances_tag: latest-alpine
glances_expose_port: 8083
glances_portainer_stack_name: glances
glances_container_name: glances
glances_restart_policy: unless-stopped
glances_pid: host

@ -1,21 +0,0 @@
---
- name: "Glances | Update Portainer."
chatton.portainer.portainer_stack:
username: admin
password: '{{ portainer.password }}'
base_url: '{{ portainer_base_url }}'
stack_name: '{{ glances_portainer_stack_name }}'
endpoint_id: '{{ portainer_endpoint }}'
state: present
definition:
services:
glances:
image: "{{ glances_image }}:{{ glances_tag }}"
restart: "{{ glances_restart_policy }}"
pid: "{{ glances_pid }}"
ports:
- "{{ glances_expose_port}}:61208"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- "GLANCES_OPT=-w"

@ -1,22 +0,0 @@
---
linkding_image: sissbruecker/linkding
linkding_tag: latest
linkding_backup_enabled: true
linkding_backup_schedule: "nightly"
linkding_expose_port: 9090
linkding_portainer_stack_name: linkding
linkding_container_name: linkding
linkding_restart_policy: unless-stopped
# Environment variables
linkding_websocket_enabled: true
linkding_sends_allowed: true
linkding_emergency_access_allowed: true
linkding_domain: "https://vault.cianhatton.ie"
linkding_signups_allowed: false
linkding_webvault_enabled: true
# Backup variables
linkding_docker_backup_restore_force: false
linkding_docker_backup_restore_latest_s3_key: true
linkding_docker_backup_fail_on_no_s3_backups: false

@ -1,35 +0,0 @@
---
- name: "Linkding | Restore any missing volumes from S3"
ansible.builtin.include_role:
name: chatton.docker_backup.docker_s3_volume_restore
vars:
docker_backup_restore_force: "{{ linkding_docker_backup_restore_force }}"
docker_backup_restore_latest_s3_key: "{{ linkding_docker_backup_restore_latest_s3_key }}"
docker_backup_fail_on_no_s3_backups: "{{ linkding_docker_backup_fail_on_no_s3_backups }}"
docker_backup_s3_volume:
name: "{{ linkding_portainer_stack_name }}_data"
- name: "Linkding | Update Portainer."
chatton.portainer.portainer_stack:
username: admin
password: '{{ portainer.password }}'
base_url: '{{ portainer_base_url }}'
stack_name: '{{ linkding_portainer_stack_name }}'
endpoint_id: '{{ portainer_endpoint }}'
state: present
definition:
version: '3'
services:
linkding:
labels:
ie.cianhatton.backup.enabled: "{{ linkding_backup_enabled }}"
ie.cianhatton.backup.schedule: "{{ linkding_backup_schedule }}"
container_name: "{{ linkding_container_name }}"
image: "{{ linkding_image }}:{{ linkding_tag }}"
ports:
- "{{ linkding_expose_port }}:9090"
volumes:
- "data:/etc/linkding/data"
restart: "{{ linkding_restart_policy }}"
volumes:
data: {}

@ -1,22 +0,0 @@
---
vaultwarden_image: vaultwarden/server
vaultwarden_tag: 1.28.1
vaultwarden_backup_enabled: true
vaultwarden_backup_schedule: "nightly"
vaultwarden_expose_port: 80
vaultwarden_portainer_stack_name: vaultwarden
vaultwarden_container_name: vaultwarden
vaultwarden_restart_policy: unless-stopped
# Environment variables
vaultwarden_websocket_enabled: true
vaultwarden_sends_allowed: true
vaultwarden_emergency_access_allowed: true
vaultwarden_domain: "https://vault.cianhatton.ie"
vaultwarden_signups_allowed: false
vaultwarden_webvault_enabled: true
# Backup variables
vaultwarden_docker_backup_restore_force: false
vaultwarden_docker_backup_restore_latest_s3_key: true
vaultwarden_docker_backup_fail_on_no_s3_backups: false

@ -1,43 +0,0 @@
---
- name: "Vaultwarden | Restore any missing volumes from S3"
ansible.builtin.include_role:
name: chatton.docker_backup.docker_s3_volume_restore
vars:
docker_backup_restore_force: "{{ vaultwarden_docker_backup_restore_force }}"
docker_backup_restore_latest_s3_key: "{{ vaultwarden_docker_backup_restore_latest_s3_key }}"
docker_backup_fail_on_no_s3_backups: "{{ vaultwarden_docker_backup_fail_on_no_s3_backups }}"
docker_backup_s3_volume:
name: "{{ vaultwarden_portainer_stack_name }}_data"
- name: "Vaultwarden | Update Portainer."
chatton.portainer.portainer_stack:
username: admin
password: '{{ portainer.password }}'
base_url: '{{ portainer_base_url }}'
stack_name: '{{ vaultwarden_portainer_stack_name }}'
endpoint_id: '{{ portainer_endpoint }}'
state: present
definition:
version: '3.3'
services:
vaultwarden:
labels:
ie.cianhatton.backup.enabled: "{{ vaultwarden_backup_enabled }}"
ie.cianhatton.backup.schedule: "{{ vaultwarden_backup_schedule }}"
image: "{{ vaultwarden_image }}:{{ vaultwarden_tag }}"
container_name: "{{ vaultwarden_container_name }}"
environment:
WEBSOCKET_ENABLED: "{{ vaultwarden_websocket_enabled }}"
SENDS_ALLOWED: "{{ vaultwarden_sends_allowed }}"
EMERGENCY_ACCESS_ALLOWED: "{{ vaultwarden_emergency_access_allowed }}"
WEB_VAULT_ENABLED: "{{ vaultwarden_webvault_enabled }}"
DOMAIN: "{{ vaultwarden_domain }}"
ADMIN_TOKEN: "{{ vaultwarden_admin_token }}"
SIGNUPS_ALLOWED: "{{ vaultwarden_signups_allowed }}"
restart: "{{ vaultwarden_restart_policy }}"
ports:
- "{{ vaultwarden_expose_port }}:80"
volumes:
- data:/data
volumes:
data: {}

@ -0,0 +1,25 @@
---
version: "3.1"
services:
bookstack:
labels:
ie.cianhatton.backup.enabled: "true"
ie.cianhatton.backup.schedule: "{{ backups.schedule_keys.nightly }}"
image: "{{ template_vars.image }}:{{ template_vars.tag }}"
container_name: bookstack
environment:
- PUID=1000
- PGID=1000
- DB_HOST=qnap
- DB_USER=bookstack
- DB_PASS="{{ bookstack_password }}"
- DB_DATABASE=bookstackapp
- APP_URL="https://bookstack.cianhatton.ie"
volumes:
- config:/config
ports:
- 6875:80
restart: unless-stopped
volumes:
config:

@ -0,0 +1,52 @@
---
version: '3.5'
services:
{% if template_vars.dashdot %}
dash-dot:
container_name: dashdot
image: mauricenino/dashdot:latest
restart: unless-stopped
privileged: true
ports:
- '3010:3001'
volumes:
- /:/mnt/host:ro
{% endif %}
{% if template_vars.dashy %}
dashy:
container_name: dashy
image: lissy93/dashy
volumes:
- /etc/config/dashy/dashy-config.yml:/app/public/conf.yml
ports:
- 4000:80
environment:
- NODE_ENV=production
- UID=1000
- GID=1000
# Specify restart policy
restart: unless-stopped
# Configure healthchecks
healthcheck:
test: ['CMD', 'node', '/app/services/healthcheck']
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s
{% endif %}
{% if template_vars.glances %}
glances:
image: nicolargo/glances:latest-alpine
restart: unless-stopped
pid: host
ports:
- "8083:61208"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- "GLANCES_OPT=-w"
{% endif %}

@ -0,0 +1,16 @@
---
version: '3'
services:
linkding:
labels:
ie.cianhatton.backup.enabled: "true"
ie.cianhatton.backup.schedule: "{{backups.schedule_keys.nightly}}"
container_name: "linkding"
image: sissbruecker/linkding:latest
ports:
- "9090:9090"
volumes:
- "data:/etc/linkding/data"
restart: unless-stopped
volumes:
data:

@ -0,0 +1,23 @@
---
version: '3.3'
services:
vaultwarden:
labels:
ie.cianhatton.backup.enabled: "true"
ie.cianhatton.backup.schedule: "{{ backups.schedule_keys.nightly }}"
image: "{{ template_vars.image }}:{{ template_vars.tag }}"
volumes:
- data:/data
environment:
WEBSOCKET_ENABLED: true
SENDS_ALLOWED: true
EMERGENCY_ACCESS_ALLOWED: true
WEB_VAULT_ENABLED: true
DOMAIN: "https://vault.cianhatton.ie"
ADMIN_TOKEN: "{{ vaultwarden_admin_token }}"
SIGNUPS_ALLOWED: false
restart: unless-stopped
ports:
- 80:80
volumes:
data:
Loading…
Cancel
Save