Compare commits
8 Commits
4d3a5933c0
...
39b35b30a9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39b35b30a9 | ||
|
|
6baab11851 | ||
|
|
543a34f60d | ||
|
|
4e4f824958 | ||
|
|
a8a7dfc688 | ||
|
|
f52ba4eced | ||
|
|
303d3a384a | ||
|
|
d6083ec2be |
@@ -52,4 +52,4 @@
|
||||
state: quadlet
|
||||
quadlet_file_mode: "0600"
|
||||
quadlet_options: "{{ _container_quadlet_options }}"
|
||||
notify: "Restart container service {{ container_name }}"
|
||||
notify: Restart container service {{ container_name }}
|
||||
|
||||
@@ -6,3 +6,4 @@
|
||||
skip_existing: "{{ item.value is not defined }}"
|
||||
no_log: true
|
||||
loop: "{{ container_secrets }}"
|
||||
notify: Restart container service {{ container_name }}
|
||||
|
||||
1
roles/grafana/README.md
Normal file
1
roles/grafana/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Installs and configures grafana
|
||||
15
roles/grafana/defaults/main.yaml
Normal file
15
roles/grafana/defaults/main.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
grafana_additional_networks: []
|
||||
|
||||
grafana_oauth_name: ""
|
||||
grafana_oauth_client_id: ""
|
||||
grafana_oauth_auth_url: ""
|
||||
grafana_oauth_token_url: ""
|
||||
grafana_oauth_api_url: ""
|
||||
grafana_oauth_scopes:
|
||||
- openid
|
||||
- profile
|
||||
- email
|
||||
grafana_oauth_role_attribute_path: ""
|
||||
grafana_oauth_allow_sign_up: true
|
||||
grafana_oauth_auto_login: true
|
||||
80
roles/grafana/meta/argument_specs.yml
Normal file
80
roles/grafana/meta/argument_specs.yml
Normal file
@@ -0,0 +1,80 @@
|
||||
---
|
||||
argument_specs:
|
||||
main:
|
||||
description: Installs and configures grafana
|
||||
options:
|
||||
grafana_domain:
|
||||
description: The domain grafana should be available on
|
||||
type: str
|
||||
required: true
|
||||
grafana_additional_networks:
|
||||
description: >-
|
||||
A list of additional podman networks for the grafana container (in
|
||||
addition to grafana network).
|
||||
type: list
|
||||
required: false
|
||||
default: []
|
||||
elements: str
|
||||
|
||||
grafana_oauth_name:
|
||||
description: >-
|
||||
Name that refers to the generic OAuth2 authentication from the Grafana
|
||||
user interface. Required to enable OAuth authentication.
|
||||
type: str
|
||||
required: false
|
||||
default: ""
|
||||
grafana_oauth_client_id:
|
||||
description: >-
|
||||
Client ID provided by your OAuth2 app. Required if OAuth is enabled.
|
||||
type: str
|
||||
required: false
|
||||
default: ""
|
||||
grafana_oauth_auth_url:
|
||||
description: Authorization endpoint of your OAuth2 provider. Required if OAuth is enabled.
|
||||
type: str
|
||||
required: false
|
||||
default: ""
|
||||
grafana_oauth_token_url:
|
||||
description: Endpoint used to obtain the OAuth2 access token.
|
||||
type: str
|
||||
required: false
|
||||
default: ""
|
||||
grafana_oauth_api_url:
|
||||
description: Endpoint used to obtain user information compatible with OpenID UserInfo.
|
||||
type: str
|
||||
required: false
|
||||
default: ""
|
||||
grafana_oauth_scopes:
|
||||
description: List of OAuth2 scopes.
|
||||
type: list
|
||||
required: false
|
||||
elements: str
|
||||
default:
|
||||
- openid
|
||||
- profile
|
||||
- email
|
||||
grafana_oauth_role_attribute_path:
|
||||
description: >-
|
||||
JMESPath expression to use for Grafana role lookup. Grafana will first
|
||||
evaluate the expression using the OAuth2 ID token. If no role is found,
|
||||
the expression will be evaluated using the user information obtained
|
||||
from the UserInfo endpoint. The result of the evaluation should be
|
||||
a valid Grafana role (Viewer, Editor, Admin or GrafanaAdmin).
|
||||
type: str
|
||||
required: false
|
||||
default: ""
|
||||
grafana_oauth_allow_sign_up:
|
||||
description: >-
|
||||
Controls Grafana user creation through the generic OAuth2 login. Only
|
||||
existing Grafana users can log in with generic OAuth if set to false.
|
||||
type: bool
|
||||
required: false
|
||||
default: true
|
||||
grafana_oauth_auto_login:
|
||||
description: >-
|
||||
Whether to enable users to bypass the login screen and automatically
|
||||
log in. This setting is ignored if you configure multiple auth
|
||||
providers to use auto-login.
|
||||
type: bool
|
||||
required: false
|
||||
default: true
|
||||
40
roles/grafana/tasks/main.yml
Normal file
40
roles/grafana/tasks/main.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
- name: Grafana
|
||||
ansible.builtin.import_role:
|
||||
name: service
|
||||
vars:
|
||||
service_name: grafana
|
||||
service_container_image: "docker.io/grafana/grafana:latest"
|
||||
service_container_mounts:
|
||||
- type: volume
|
||||
source: data
|
||||
destination: /var/lib/grafana
|
||||
service_container_http_port: 3000
|
||||
service_domains:
|
||||
- "{{ grafana_domain }}"
|
||||
service_database_type: postgres
|
||||
service_postgres_tag: 17-alpine
|
||||
service_container_additional_networks: "{{ grafana_additional_networks }}"
|
||||
service_container_env:
|
||||
GF_DATABASE_TYPE: postgres
|
||||
GF_DATABASE_HOST: grafana-postgres:5432
|
||||
GF_DATABASE_NAME: grafana
|
||||
GF_DATABASE_USER: grafana
|
||||
GF_DATABASE_PASSWORD__FILE: /run/secrets/postgres
|
||||
GF_SERVER_DOMAIN: "{{ grafana_domain }}"
|
||||
GF_SERVER_ROOT_URL: "https://{{ grafana_domain }}"
|
||||
|
||||
GF_AUTH_GENERIC_OAUTH_ENABLED: "{{ 'true' if grafana_oauth_name | length > 0 else 'false' }}"
|
||||
GF_AUTH_GENERIC_OAUTH_NAME: "{{ grafana_oauth_name }}"
|
||||
GF_AUTH_GENERIC_OAUTH_CLIENT_ID: "{{ grafana_oauth_client_id }}"
|
||||
GF_AUTH_GENERIC_OAUTH_AUTH_URL: "{{ grafana_oauth_auth_url }}"
|
||||
GF_AUTH_GENERIC_OAUTH_TOKEN_URL: "{{ grafana_oauth_token_url }}"
|
||||
GF_AUTH_GENERIC_OAUTH_API_URL: "{{ grafana_oauth_userinfo_url }}"
|
||||
GF_AUTH_GENERIC_OAUTH_SCOPES: "{{ grafana_oauth_scopes | join(' ') }}"
|
||||
GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP: "{{ 'true' if grafana_oauth_allow_sign_up else 'false' }}"
|
||||
GF_AUTH_GENERIC_OAUTH_AUTO_LOGIN: "{{ 'true' if grafana_oauth_auto_login else 'false' }}"
|
||||
GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_PATH: "{{ grafana_oauth_role_attribute_path }}"
|
||||
GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_STRICT: "true"
|
||||
GF_AUTH_GENERIC_OAUTH_ALLOW_ASSIGN_GRAFANA_ADMIN: "true"
|
||||
GF_AUTH_GENERIC_OAUTH_USE_PKCE: "true"
|
||||
GF_AUTH_GENERIC_OAUTH_LOGIN_ATTRIBUTE_PATH: preferred_username
|
||||
2
roles/image/README.md
Normal file
2
roles/image/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
Sets up podman image with systemd unit (quadlet)
|
||||
The image unit filename is `image_name` with / replaced by _
|
||||
1
roles/oauth2_proxy/README.md
Normal file
1
roles/oauth2_proxy/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Sets up a oauth2-proxy container
|
||||
17
roles/oauth2_proxy/meta/argument_specs.yml
Normal file
17
roles/oauth2_proxy/meta/argument_specs.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
argument_specs:
|
||||
main:
|
||||
description: "Sets up a oauth2-proxy container"
|
||||
options:
|
||||
oauth2_proxy_oidc_issuer_url:
|
||||
description: the OpenID Connect issuer URL
|
||||
type: str
|
||||
required: true
|
||||
oauth2_proxy_client_id:
|
||||
description: the OAuth client ID
|
||||
type: str
|
||||
required: true
|
||||
oauth2_proxy_client_secret:
|
||||
description: the OAuth client secret
|
||||
type: str
|
||||
required: true
|
||||
24
roles/oauth2_proxy/tasks/main.yml
Normal file
24
roles/oauth2_proxy/tasks/main.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
- name: OAuth2 Proxy
|
||||
ansible.builtin.import_role:
|
||||
name: service
|
||||
vars:
|
||||
service_name: oauth2-proxy
|
||||
service_container_image: "quay.io/oauth2-proxy/oauth2-proxy:latest-alpine"
|
||||
service_container_http_port: 4180
|
||||
service_container_command:
|
||||
- --config
|
||||
- /oauth2-proxy.cfg
|
||||
- --client-secret-file
|
||||
- /run/secrets/client_secret
|
||||
service_container_mounts:
|
||||
- type: template
|
||||
source: oauth2-proxy.cfg.j2
|
||||
destination: /oauth2-proxy.cfg
|
||||
service_container_secrets:
|
||||
- name: cookie_secret
|
||||
length: 32
|
||||
type: env
|
||||
target: OAUTH2_PROXY_COOKIE_SECRET
|
||||
- name: client_secret
|
||||
value: "{{ oauth2_proxy_client_secret }}"
|
||||
11
roles/oauth2_proxy/templates/oauth2-proxy.cfg.j2
Normal file
11
roles/oauth2_proxy/templates/oauth2-proxy.cfg.j2
Normal file
@@ -0,0 +1,11 @@
|
||||
# OAuth2 Proxy Configuration
|
||||
http_address = "0.0.0.0:4180"
|
||||
|
||||
# OIDC Provider Configuration
|
||||
provider = "oidc"
|
||||
oidc_issuer_url = "{{ oauth2_proxy_oidc_issuer_url }}"
|
||||
client_id = "{{ oauth2_proxy_client_id }}"
|
||||
code_challenge_method = "S256"
|
||||
skip_provider_button = "true"
|
||||
|
||||
email_domains = "*"
|
||||
@@ -2,8 +2,10 @@
|
||||
service_container_command: []
|
||||
|
||||
service_domains: []
|
||||
service_container_http_port: 0
|
||||
service_vhost_locations: []
|
||||
service_proxy_pass_host_header: true
|
||||
service_proxy_auth_type: none
|
||||
|
||||
service_container_additional_networks: []
|
||||
service_container_user: ""
|
||||
@@ -13,6 +15,7 @@ service_container_secrets: []
|
||||
service_container_env: {}
|
||||
|
||||
service_database_type: none
|
||||
service_database_additional_networks: []
|
||||
service_database_secret_type: mount
|
||||
service_database_secret_target: "{{ service_database_type }}"
|
||||
service_postgres_image: docker.io/library/postgres
|
||||
|
||||
@@ -27,11 +27,22 @@ argument_specs:
|
||||
- Required if service_domains is not empty.
|
||||
type: int
|
||||
required: false
|
||||
default: 0
|
||||
service_proxy_pass_host_header:
|
||||
description: Passed to vhost role as vhost_proxy_pass_header
|
||||
type: bool
|
||||
required: false
|
||||
default: true
|
||||
service_proxy_auth_type:
|
||||
description: >-
|
||||
Set to oauth2-proxy to use OAuth2 Proxy for vhost authentication.
|
||||
The oauth2-proxy role must be run separately.
|
||||
type: str
|
||||
required: false
|
||||
default: none
|
||||
choices:
|
||||
- none
|
||||
- oauth2-proxy
|
||||
service_vhost_locations:
|
||||
description: Passed to vhost role as vhost_locations
|
||||
type: list
|
||||
@@ -65,7 +76,9 @@ argument_specs:
|
||||
required: false
|
||||
default: ""
|
||||
service_container_additional_networks:
|
||||
description: A list of additional podman networks for the service container (in addition to service name network).
|
||||
description: >-
|
||||
A list of additional podman networks for the service container (in
|
||||
addition to service name network).
|
||||
type: list
|
||||
required: false
|
||||
default: []
|
||||
@@ -211,6 +224,14 @@ argument_specs:
|
||||
- none
|
||||
required: false
|
||||
default: none
|
||||
service_database_additional_networks:
|
||||
description: >-
|
||||
A list of additional podman networks for the database container (in
|
||||
addition to service name network).
|
||||
type: list
|
||||
required: false
|
||||
default: []
|
||||
elements: str
|
||||
service_database_secret_type:
|
||||
description: Secret type for database secret for service container
|
||||
type: str
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
- type: volume
|
||||
source: "{{ _service_database_name }}"
|
||||
destination: /var/lib/postgresql/data
|
||||
container_networks:
|
||||
- "{{ service_name }}"
|
||||
container_networks: "{{ _service_database_networks }}"
|
||||
container_secrets:
|
||||
- name: "{{ _service_database_name }}"
|
||||
target: "{{ service_database_type }}"
|
||||
|
||||
@@ -40,6 +40,10 @@
|
||||
container_wants: "{{ _service_container_wants }}"
|
||||
container_auto_update: "{{ service_auto_update }}"
|
||||
|
||||
- name: Socat for {{ service_name }}
|
||||
ansible.builtin.include_tasks: socat.yaml
|
||||
when: service_container_http_port > 0
|
||||
|
||||
- name: Reverse proxy for {{ service_name }}
|
||||
ansible.builtin.include_tasks: proxy.yaml
|
||||
when: service_domains | length > 0
|
||||
|
||||
@@ -1,29 +1,4 @@
|
||||
---
|
||||
- name: Socat socket for {{ service_name }}
|
||||
ansible.builtin.template:
|
||||
src: socat.socket.j2
|
||||
dest: /etc/systemd/system/{{ service_name }}-socat.socket
|
||||
mode: "0644"
|
||||
notify: Restart socat socket for {{ service_name }}
|
||||
|
||||
- name: Socat container for {{ service_name }}
|
||||
ansible.builtin.import_role:
|
||||
name: container
|
||||
vars:
|
||||
container_name: "{{ service_name }}-socat"
|
||||
container_image: "docker.io/alpine/socat:latest"
|
||||
container_command:
|
||||
- "ACCEPT-FD:3,fork"
|
||||
- "TCP:{{ service_name }}:{{ service_container_http_port }}"
|
||||
container_user: nobody
|
||||
container_networks:
|
||||
- "{{ service_name }}"
|
||||
container_requires:
|
||||
- "{{ service_name }}-socat.socket"
|
||||
- "{{ service_name }}.service"
|
||||
container_auto_start: false
|
||||
container_auto_update: "{{ service_auto_update }}"
|
||||
|
||||
- name: Reverse proxy for {{ service_name }}
|
||||
ansible.builtin.import_role:
|
||||
name: uumas.general.vhost
|
||||
@@ -34,4 +9,7 @@
|
||||
vhost_proxy_target_netproto: unix
|
||||
vhost_proxy_target_socket: "/run/{{ service_name }}-socat.sock"
|
||||
vhost_proxy_headers: "{{ _service_proxy_headers }}"
|
||||
vhost_locations: "{{ service_vhost_locations }}"
|
||||
vhost_proxy_auth_socket: "{{ _service_oauth2_socket }}"
|
||||
vhost_proxy_auth_uri: /oauth2/auth
|
||||
vhost_proxy_auth_unauthorized_redir: "/oauth2/sign_in?rd={scheme}://{host}{uri}"
|
||||
vhost_locations: "{{ _service_vhost_locations }}"
|
||||
|
||||
26
roles/service/tasks/socat.yaml
Normal file
26
roles/service/tasks/socat.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
- name: Socat socket for {{ service_name }}
|
||||
ansible.builtin.template:
|
||||
src: socat.socket.j2
|
||||
dest: /etc/systemd/system/{{ service_name }}-socat.socket
|
||||
mode: "0644"
|
||||
notify: Restart socat socket for {{ service_name }}
|
||||
|
||||
- name: Socat container for {{ service_name }}
|
||||
ansible.builtin.import_role:
|
||||
name: container
|
||||
vars:
|
||||
container_name: "{{ service_name }}-socat"
|
||||
container_image: "docker.io/alpine/socat:latest"
|
||||
container_command:
|
||||
- "ACCEPT-FD:3,fork"
|
||||
- "TCP:{{ service_name }}:{{ service_container_http_port }}"
|
||||
container_user: nobody
|
||||
container_networks:
|
||||
- "{{ service_name }}"
|
||||
container_requires:
|
||||
- "{{ service_name }}-socat.socket"
|
||||
- "{{ service_name }}.service"
|
||||
container_auto_start: false
|
||||
container_auto_update: "{{ service_auto_update }}"
|
||||
|
||||
8
roles/service/vars/main/database.yaml
Normal file
8
roles/service/vars/main/database.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
_service_setup_database: "{{ service_database_type != 'none' }}"
|
||||
_service_database_name: "{{ service_name }}-{{ service_database_type }}"
|
||||
_service_database_networks: >-
|
||||
{{
|
||||
[service_name] +
|
||||
service_database_additional_networks
|
||||
}}
|
||||
@@ -1,7 +1,4 @@
|
||||
---
|
||||
_service_setup_database: "{{ service_database_type != 'none' }}"
|
||||
_service_database_name: "{{ service_name }}-{{ service_database_type }}"
|
||||
|
||||
_service_container_networks: "{{ [service_name] + service_container_additional_networks }}"
|
||||
|
||||
_service_container_requires: >-
|
||||
@@ -18,7 +15,3 @@ _service_container_wants: >-
|
||||
| map(attribute='name')
|
||||
| map('regex_replace', '$', '.service')
|
||||
}}
|
||||
|
||||
_service_replacement_host_header:
|
||||
Host: "{{ service_name }}:{{ service_container_http_port }}"
|
||||
_service_proxy_headers: "{{ _service_replacement_host_header if not service_proxy_pass_host_header else {} }}"
|
||||
|
||||
18
roles/service/vars/main/proxy.yaml
Normal file
18
roles/service/vars/main/proxy.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
_service_replacement_host_header:
|
||||
Host: "{{ service_name }}:{{ service_container_http_port }}"
|
||||
_service_proxy_headers: "{{ _service_replacement_host_header if not service_proxy_pass_host_header else {} }}"
|
||||
|
||||
_service_oauth2_proxy: "{{ service_proxy_auth_type == 'oauth2-proxy' }}"
|
||||
_service_oauth2_socket: >-
|
||||
{{ '/run/oauth2-proxy-socat.sock' if _service_oauth2_proxy else '' }}
|
||||
_service_oauth2_proxy_location:
|
||||
path: /oauth2/*
|
||||
proxy_target_socket: "{{ _service_oauth2_socket }}"
|
||||
proxy_auth_socket: ""
|
||||
|
||||
_service_vhost_locations: >-
|
||||
{{
|
||||
service_vhost_locations +
|
||||
([_service_oauth2_proxy_location] if _service_oauth2_proxy else [])
|
||||
}}
|
||||
Reference in New Issue
Block a user