Skip to content

Commit 861aa93

Browse files
authored
Merge pull request #24 from jeremy-code/20-grafana
Add Grafana, Loki, Alloy containers
2 parents 5a86482 + 99f4351 commit 861aa93

18 files changed

Lines changed: 467 additions & 15 deletions

data.tf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ data "oci_secrets_secretbundle" "redis_passwords" {
3939
secret_id = each.value.id
4040
}
4141

42+
data "oci_secrets_secretbundle" "grafana_secret_key_secret" {
43+
secret_id = oci_vault_secret.grafana_secret_key_secret.id
44+
}
4245

4346
data "oci_core_images" "main" {
4447
compartment_id = oci_identity_compartment.main.id

dns.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ resource "cloudflare_dns_record" "www" {
1717
}
1818

1919
resource "cloudflare_dns_record" "tunnels" {
20-
for_each = toset(["@", "webdav", "vault", "rss", "status", "auth", "wireguard"])
20+
for_each = toset(["@", "webdav", "vault", "rss", "status", "auth", "wireguard", "logs"])
2121
content = "${cloudflare_zero_trust_tunnel_cloudflared.main.id}.cfargotunnel.com"
2222
name = each.value
2323
proxied = true

files/authelia.configuration.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ notifier:
9292
identity_providers:
9393
oidc:
9494
hmac_secret: '{{ secret "/run/secrets/hmac-secret" }}'
95+
claims_policies:
96+
# https://www.authelia.com/integration/openid-connect/clients/grafana/#configuration-escape-hatch
97+
grafana:
98+
id_token:
99+
- email
100+
- name
101+
- groups
102+
- preferred_username
95103
jwks:
96104
- key_id: "main"
97105
algorithm: "RS256"
@@ -169,3 +177,23 @@ identity_providers:
169177
pre_configured_consent_duration: 1 week
170178
require_pkce: true
171179
token_endpoint_auth_method: client_secret_post
180+
- client_id: '{{ env "GRAFANA_CLIENT_ID" }}'
181+
client_name: "Grafana"
182+
client_secret: '{{ env "GRAFANA_CLIENT_SECRET" }}'
183+
require_pkce: true
184+
pkce_challenge_method: "S256"
185+
redirect_uris:
186+
- 'https://logs.{{ env "SERVER_DOMAIN" }}/login/generic_oauth'
187+
scopes:
188+
- "openid"
189+
- "profile"
190+
- "groups"
191+
- "email"
192+
claims_policy: "grafana"
193+
response_types:
194+
- "code"
195+
grant_types:
196+
- "authorization_code"
197+
access_token_signed_response_alg: "none"
198+
userinfo_signed_response_alg: "none"
199+
token_endpoint_auth_method: "client_secret_basic"

files/compose.yaml

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ x-default-service: &default-service
55
cap_drop: [ALL]
66
security_opt: [no-new-privileges]
77
pull_policy: weekly
8+
logging:
9+
driver: syslog
10+
options:
11+
tag: "{{.Name}}"
12+
syslog-facility: "local0"
813

914
services:
1015
vaultwarden:
@@ -69,6 +74,7 @@ services:
6974
- freshrss
7075
- authelia
7176
- wg-easy
77+
- grafana
7278
env_file:
7379
- gatus.env
7480
volumes:
@@ -93,6 +99,7 @@ services:
9399
- freshrss
94100
- authelia
95101
- wg-easy
102+
- grafana
96103
volumes:
97104
- "/mnt/oraclevdb/cloudflared:/user/nonroot/.cloudflared/"
98105
command: tunnel run
@@ -218,6 +225,64 @@ services:
218225
uid: "999"
219226
gid: "999"
220227

228+
grafana:
229+
<<: *default-service
230+
container_name: grafana
231+
image: grafana/grafana:latest
232+
env_file: ./grafana.env
233+
user: "472:0" # user grafana, group root
234+
volumes:
235+
- /mnt/oraclevdb/grafana/:/var/lib/grafana/
236+
configs:
237+
- source: grafana-ini
238+
target: /etc/grafana/grafana.ini
239+
uid: "472"
240+
gid: "0"
241+
- source: grafana-datasources
242+
target: /etc/grafana/provisioning/datasources/datasources.yaml
243+
uid: "472"
244+
gid: "0"
245+
- source: grafana-dashboards
246+
target: /etc/grafana/provisioning/dashboards/dashboards.yaml
247+
uid: "472"
248+
gid: "0"
249+
secrets:
250+
- grafana-database-url
251+
252+
loki:
253+
<<: *default-service
254+
container_name: loki
255+
image: grafana/loki:latest
256+
user: 10001:10001 # loki user
257+
volumes:
258+
- /mnt/oraclevdb/loki/:/loki/
259+
configs:
260+
- source: loki-config
261+
target: /etc/loki/local-config.yaml
262+
uid: "10001"
263+
gid: "10001"
264+
265+
alloy:
266+
<<: *default-service
267+
container_name: alloy
268+
image: grafana/alloy:latest
269+
user: 473:473 # alloy user
270+
ports:
271+
- 514:514/tcp
272+
# https://github.com/grafana/alloy/blob/a473efe2b676ba826ec1ba68897b6b1f475bcbbc/Dockerfile#L82
273+
command: >
274+
run
275+
/etc/alloy/config.alloy
276+
--server.http.listen-addr=0.0.0.0:12345
277+
--storage.path=/var/lib/alloy/data
278+
volumes:
279+
- /mnt/oraclevdb/alloy/:/var/lib/alloy/data
280+
configs:
281+
- source: alloy-config
282+
target: /etc/alloy/config.alloy
283+
uid: "473"
284+
gid: "473"
285+
221286
configs:
222287
rclone-config:
223288
file: ./rclone.conf
@@ -240,6 +305,16 @@ configs:
240305
file: ./authelia.configuration.yml
241306
redis-config:
242307
file: ./redis.conf
308+
grafana-ini:
309+
file: ./grafana.ini
310+
grafana-datasources:
311+
file: ./datasources.yaml
312+
grafana-dashboards:
313+
file: ./dashboards.yaml
314+
loki-config:
315+
file: ./loki-config.yaml
316+
alloy-config:
317+
file: ./config.alloy
243318

244319
secrets:
245320
vaultwarden-database-url:
@@ -262,3 +337,5 @@ secrets:
262337
file: "./authelia-redis-password"
263338
redis-users-acl:
264339
file: "./redis.users.acl"
340+
grafana-database-url:
341+
file: "./grafana-database-url"

files/config.alloy

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
logging {
2+
format = "logfmt"
3+
level = "info"
4+
}
5+
6+
7+
loki.relabel "syslog" {
8+
forward_to = []
9+
10+
rule {
11+
action = "labelmap"
12+
regex = "__syslog_(.+)"
13+
}
14+
15+
rule {
16+
action = "labelmap"
17+
regex = "message_(.+)"
18+
}
19+
}
20+
21+
loki.source.syslog "syslog_receiver" {
22+
listener {
23+
address = "0.0.0.0:514"
24+
protocol = "tcp"
25+
labels = { job = "syslog" }
26+
}
27+
relabel_rules = loki.relabel.syslog.rules
28+
29+
forward_to = [loki.write.default.receiver]
30+
}
31+
32+
loki.write "default" {
33+
endpoint {
34+
url = "http://loki:3100/loki/api/v1/push"
35+
}
36+
}

files/gatus-config.yaml

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ security:
1414
web:
1515
port: 8080
1616

17+
ui:
18+
default-sort-by: group
19+
1720
alerting:
1821
email:
1922
enabled: true
@@ -76,8 +79,8 @@ endpoints:
7679
<<: *status-200
7780
- name: FreshRSS
7881
group: core
79-
url: "https://rss.${SERVER_DOMAIN}"
80-
<<: *status-401
82+
url: "https://rss.${SERVER_DOMAIN}/api"
83+
<<: *status-200
8184
- name: Authelia
8285
group: core
8386
url: "https://auth.${SERVER_DOMAIN}/api/health"
@@ -90,6 +93,14 @@ endpoints:
9093
group: core
9194
url: "https://wireguard.${SERVER_DOMAIN}"
9295
<<: *status-200
96+
- name: Grafana
97+
group: core
98+
url: "https://logs.${SERVER_DOMAIN}/api/health"
99+
<<: *status-200
100+
conditions: &grafana-conditions
101+
- "[STATUS] == 200"
102+
- "[RESPONSE_TIME] < 1000"
103+
- "[BODY].database == ok"
93104
# Internal
94105
- name: Vaultwarden (Internal)
95106
group: internal
@@ -106,8 +117,8 @@ endpoints:
106117
<<: *status-200
107118
- name: FreshRSS (Internal)
108119
group: internal
109-
url: "http://freshrss:80"
110-
<<: *status-401
120+
url: "http://freshrss:80/api"
121+
<<: *status-200
111122
- name: Authelia (Internal)
112123
group: internal
113124
url: "http://authelia:9091/api/health"
@@ -117,6 +128,11 @@ endpoints:
117128
group: internal
118129
url: "http://wg-easy:51821"
119130
<<: *status-200
131+
- name: Grafana (Internal)
132+
group: internal
133+
url: "http://grafana:3000/api/health"
134+
<<: *status-200
135+
conditions: *grafana-conditions
120136
- name: Folding@home
121137
group: internal
122138
url: "http://foldingathome:7396"

files/grafana/dashboards.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: 1
2+
3+
providers:
4+
- name: "Redis"
5+
type: file
6+
options:
7+
path: /var/lib/grafana/plugins/redis-datasource/dashboards

files/grafana/datasources.yaml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
apiVersion: 1
2+
3+
prune: true
4+
5+
datasources:
6+
- &mysql-datasource
7+
name: MySQL (Grafana)
8+
type: mysql
9+
url: $_GRAFANA_MYSQL_URL
10+
user: $_GRAFANA_MYSQL_USERNAME
11+
jsonData:
12+
database: grafana
13+
secureJsonData:
14+
password: $_GRAFANA_MYSQL_PASSWORD
15+
- <<: *mysql-datasource
16+
name: MySQL (Authelia)
17+
jsonData:
18+
database: authelia
19+
- <<: *mysql-datasource
20+
name: MySQL (FreshRSS)
21+
jsonData:
22+
database: freshrss
23+
- name: Redis
24+
type: redis-datasource
25+
url: redis://redis:6379
26+
jsonData:
27+
client: standalone
28+
acl: true
29+
user: $_GRAFANA_REDIS_USERNAME
30+
secureJsonData:
31+
password: $_GRAFANA_REDIS_PASSWORD
32+
- name: Loki
33+
type: loki
34+
access: proxy
35+
url: http://loki:3100
36+
jsonData:
37+
timeout: 60
38+
maxLines: 1000

files/grafana/grafana.ini

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
########################## Grafana Configuration #########################
2+
3+
#################################### Server ##############################
4+
[server]
5+
protocol = http
6+
http_addr = 0.0.0.0
7+
http_port = 3000
8+
domain = ${HOSTNAME}
9+
enforce_domain = false
10+
root_url = https://logs.%(domain)s/
11+
serve_from_sub_path = false
12+
router_logging = false
13+
static_root_path = public
14+
enable_gzip = false
15+
16+
#################################### Database ############################
17+
[database]
18+
url = $__file{/run/secrets/grafana-database-url}
19+
conn_max_lifetime = 14400 # 4 hours (14400 seconds)
20+
21+
#################################### Security ############################
22+
[security]
23+
secret_key = ${SECRET_KEY_SECRET}
24+
disable_initial_admin_creation = true
25+
brute_force_login_protection_max_attempts = 3
26+
cookie_secure = true
27+
28+
#################################### Users ###############################
29+
[users]
30+
allow_sign_up=false
31+
allow_org_create=false
32+
default_theme=system
33+
34+
[auth]
35+
disable_login_form=true
36+
37+
#################################### Generic OAuth #######################
38+
[auth.generic_oauth]
39+
enabled = true
40+
name = Authelia
41+
icon = signin
42+
client_id = ${CLIENT_ID}
43+
client_secret = ${CLIENT_SECRET}
44+
auth_url = https://auth.${HOSTNAME}/api/oidc/authorization
45+
token_url = https://auth.${HOSTNAME}/api/oidc/token
46+
api_url = https://auth.${HOSTNAME}/api/oidc/userinfo
47+
auth_style = InHeader
48+
scopes = openid profile email groups
49+
empty_scopes = false
50+
login_attribute_path = preferred_username
51+
name_attribute_path = name
52+
role_attribute_path = contains(groups[*], 'super_admin') && 'GrafanaAdmin' || contains(groups[*], 'admin') && 'Admin' || contains(groups[*], 'editor') && 'Editor' || 'Viewer'
53+
allow_assign_grafana_admin = true
54+
groups_attribute_path = groups
55+
use_pkce = true
56+
57+
#################################### SMTP / Emailing #####################
58+
[smtp]
59+
enabled=true
60+
host=${SMTP_HOST}
61+
user=${SMTP_USERNAME}
62+
password=${SMTP_PASSWORD}
63+
from_address=${SMTP_EMAIL_FROM}
64+
from_name=grafana
65+
66+
#################################### Unified Alerting ####################
67+
[unified_alerting]
68+
enabled = true
69+
70+
[date_formats]
71+
use_browser_locale = true
72+
default_timezone = browser

0 commit comments

Comments
 (0)