Compare commits

..

13 Commits

Author SHA1 Message Date
Stéphan Sainléger
31bcaab87f chg: [outline] add restart unless-stopped directive 2026-09-11 15:04:53 +02:00
Boris Gallet
e2f363439c chg: [carbone-ee] upd README with usage 2026-09-11 15:04:53 +02:00
default
dcebdd40a9 chg: [outline] upd to 1.6.1 2026-09-11 15:04:53 +02:00
Boris Gallet
ea874a54ad new: [carbone-ee] new charm for carbone.io 2026-09-11 15:04:53 +02:00
Stéphan Sainléger
a4c1c62952 fix: [outline] correct typo on postgres extention pg_trgm 2026-09-11 15:04:53 +02:00
Boris Gallet
3ef0857c56 fix: [plausible] smpt server config + init first install 2026-09-11 15:04:53 +02:00
Boris Gallet
58c5261756 fix: [outline] remove default OIDC_DISPLAY_NAME 2026-09-11 15:04:53 +02:00
default
56a78a93ee new: [plausible] add charm 2026-09-11 15:04:53 +02:00
Boris Gallet
415805341f chg: [outline] upd to 0.83.0 2026-09-11 15:04:53 +02:00
Boris Gallet
20e8ba665d fix: [outline] fix smtp server config 2026-09-11 15:04:53 +02:00
default
be31b80024 chg: [outline] upd to 0.81.1 2026-09-11 15:04:53 +02:00
Boris Gallet
710ffb15c6 fix: [n8n] upd 1.45.1 and fix email invitation 2026-09-11 15:04:53 +02:00
default
414895b673 new: [outline] add new charm 2026-09-11 15:04:53 +02:00
28 changed files with 359 additions and 219 deletions

17
carbone/README.org Normal file
View File

@@ -0,0 +1,17 @@
# -*- ispell-local-dictionary: "english" -*-
* Info
From: Carbone https://hub.docker.com/r/carbone/carbone-ee#running-carbone-community-edition-forever-free
## Usage :
ex :
```
carbone:
relations:
web-proxy:
frontend:
domain: carbone.dev1.elabore.coop
```

22
carbone/metadata.yml Normal file
View File

@@ -0,0 +1,22 @@
## From carbone/carbone-ee:full-5.4.2
docker-image: docker.0k.io/carbone-ee:5.4.2
data-resources:
- /app/template
uses:
web-proxy:
#constraint: required | recommended | optional
#auto: pair | summon | none ## default: pair
constraint: recommended
auto: pair
solves:
proxy: "Public access"
default-options:
target: !var-expand ${MASTER_BASE_SERVICE_NAME}:4000
backup:
constraint: recommended
auto: pair
solves:
backup: "Automatic regular backup"
default-options:

7
clickhouse/README.org Normal file
View File

@@ -0,0 +1,7 @@
# -*- ispell-local-dictionary: "english" -*-
* Info
This charm is provided to work with plausible charm
* Usage

21
clickhouse/hooks/init Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
## Init is run on host
## For now it is run every time the script is launched, but
## it should be launched only once after build.
## Accessible variables are:
## - SERVICE_NAME Name of current service
## - DOCKER_BASE_IMAGE Base image from which this service might be built if any
## - SERVICE_DATASTORE Location on host of the DATASTORE of this service
## - SERVICE_CONFIGSTORE Location on host of the CONFIGSTORE of this service
set -e
init-config-add "
$SERVICE_NAME:
environment:
CLICKHOUSE_SKIP_USER_SETUP: 1
healthcheck:
test: [ \"CMD-SHELL\", \"wget --no-verbose --tries=1 -O - http://127.0.0.1:8123/ping || exit 1\" ]
"

21
clickhouse/metadata.yml Normal file
View File

@@ -0,0 +1,21 @@
docker-image: docker.0k.io/clickhouse:24.12-alpine
#docker-image: clickhouse/clickhouse-server:24.12-alpine
data-resources:
- /var/lib/clickhouse
- /var/log/clickhouse-server
charm-resources:
- /etc/clickhouse-server/config.d/logs.xml
- /etc/clickhouse-server/config.d/ipv4-only.xml
- /etc/clickhouse-server/config.d/low-resources.xml
provides:
event-db:
uses:
log-rotate:
constraint: recommended
auto: pair
solves:
disk-leak: "/var/log/clickhouse-server"

View File

@@ -0,0 +1,3 @@
<clickhouse>
<listen_host>0.0.0.0</listen_host>
</clickhouse>

View File

@@ -0,0 +1,28 @@
<clickhouse>
<logger>
<level>warning</level>
<console>true</console>
</logger>
<query_log replace="1">
<database>system</database>
<table>query_log</table>
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
<engine>
ENGINE = MergeTree
PARTITION BY event_date
ORDER BY (event_time)
TTL event_date + interval 30 day
SETTINGS ttl_only_drop_parts=1
</engine>
</query_log>
<!-- Stops unnecessary logging -->
<metric_log remove="remove" />
<asynchronous_metric_log remove="remove" />
<query_thread_log remove="remove" />
<text_log remove="remove" />
<trace_log remove="remove" />
<session_log remove="remove" />
<part_log remove="remove" />
</clickhouse>

View File

@@ -0,0 +1,23 @@
<!-- https://clickhouse.com/docs/en/operations/tips#using-less-than-16gb-of-ram -->
<clickhouse>
<!--
https://clickhouse.com/docs/en/operations/server-configuration-parameters/settings#mark_cache_size -->
<mark_cache_size>524288000</mark_cache_size>
<profile>
<default>
<!-- https://clickhouse.com/docs/en/operations/settings/settings#max_threads -->
<max_threads>1</max_threads>
<!-- https://clickhouse.com/docs/en/operations/settings/settings#max_block_size -->
<max_block_size>8192</max_block_size>
<!-- https://clickhouse.com/docs/en/operations/settings/settings#max_download_threads -->
<max_download_threads>1</max_download_threads>
<!--
https://clickhouse.com/docs/en/operations/settings/settings#input_format_parallel_parsing -->
<input_format_parallel_parsing>0</input_format_parallel_parsing>
<!--
https://clickhouse.com/docs/en/operations/settings/settings#output_format_parallel_formatting -->
<output_format_parallel_formatting>0</output_format_parallel_formatting>
</default>
</profile>
</clickhouse>

View File

@@ -1,32 +0,0 @@
Description
===========
Using ``keycloak`` version 24.0
DEV info : https://www.keycloak.org/server/containers
Usage
=====
To start with ``keycloak``, just put this service in your
``compose.yml``::
keycloak:
options:
admin-password: CHANGEME
relations:
web-proxy:
frontend:
domain: id.mydomain.fr
Customize theme
===============
You can customize theme by putting your theme in
``/srv/datastore/data/keycloak/opt/keycloak/themes``
For example copy the material folder from
https://github.com/MAXIMUS-DeltaWare/material-keycloak-theme and
restart ``keycloak``.
Then go to your admin console, log in and go to the realm/themes part
to choose you new theme

View File

@@ -1,15 +0,0 @@
#FROM keycloak/keycloak:24.0.4 as builder
#
#ENV KC_METRICS_ENABLED=true
#ENV KC_FEATURES=token-exchange
#ENV KC_DB=postgres
#
#WORKDIR /opt/keycloak
## for demonstration purposes only, please make sure to use proper certificates in production instead
#RUN /opt/keycloak/bin/kc.sh build
FROM keycloak/keycloak:24.0.4
#COPY --from=builder /opt/keycloak/ /opt/keycloak/
WORKDIR /opt/keycloak
ENV KC_LOG_LEVEL=INFO
ENTRYPOINT ["/opt/keycloak/bin/kc.sh", "start", "--optimized"]

View File

@@ -1,16 +0,0 @@
FROM docker.0k.io/keycloak:17.0.1 as builder
ENV KC_METRICS_ENABLED=true
ENV KC_FEATURES=token-exchange
ENV KC_DB=postgres
RUN /opt/keycloak/bin/kc.sh build
FROM builder as inspector
ENTRYPOINT ["ls", "-l", "/opt/keycloak/lib/"]
#FROM docker.0k.io/keycloak:17.0.0
#COPY --from=builder /opt/keycloak/lib/quarkus/ /opt/keycloak/lib/quarkus/
#WORKDIR /opt/keycloak
#ENV KC_LOG_LEVEL=INFO
#ENTRYPOINT ["/opt/keycloak/bin/kc.sh", "start"]

View File

@@ -1,12 +0,0 @@
#!/bin/bash
set -e
admin_password=$(options-get admin-password) || exit 1
init-config-add "\
$MASTER_BASE_SERVICE_NAME:
environment:
KEYCLOAK_ADMIN: \"admin\"
KEYCLOAK_ADMIN_PASSWORD: \"$admin_password\"
"

View File

@@ -1,21 +0,0 @@
#!/bin/bash
. lib/common
DOMAIN=$(relation-get domain) || exit 1
#IP_HOST=$(hostname -I | awk '{print $1}')
set -e
keycloak:generate-key-if-not-exist "$DOMAIN"
config-add "\
services:
$MASTER_BASE_SERVICE_NAME:
environment:
KC_HOSTNAME: \"$DOMAIN\"
KC_PROXY: edge
KC_HTTP_ENABLED: \"true\"
KC_HOSTNAME_STRICT: \"false\"
"

View File

@@ -1,46 +0,0 @@
# -*- mode: bash -*-
KEYCLOAK_DIR=/opt/keycloak
DATASTORE_KEYCLOAK_DIR="$SERVICE_DATASTORE$KEYCLOAK_DIR"
HOST_DATASTORE_KEYCLOAK_DIR="$HOST_DATASTORE/$SERVICE_NAME$KEYCLOAK_DIR"
keycloak:generate-key-if-not-exist() {
local domain="$1" ip_host
[ -d "$DATASTORE_KEYCLOAK_DIR" ] && return 0
ip_host=$(set -o pipefail; getent ahostsv4 "$domain" | head -n 1 | cut -f 1 -d " ") || {
err "Couldn't resolve to ipv4 domain name '$domain'."
return 1
}
info "Resolved successfully '$domain' to ip '$ip_host'."
debug "DOCKER_BASE_IMAGE: $DOCKER_BASE_IMAGE"
debug "HOST_DATASTORE_KEYCLOAK_DIR:: $HOST_DATASTORE_KEYCLOAK_DIR"
mkdir -p "$DATASTORE_KEYCLOAK_DIR/conf" || return 0
docker_image_export_dir "$DOCKER_BASE_IMAGE" "/opt/keycloak" "$SERVICE_DATASTORE/opt" || return 1
uid=$(docker_get_uid "$SERVICE_NAME" "keycloak") || return 1
chown "$uid" "$DATASTORE_KEYCLOAK_DIR" -R
debug "DATASTORE_KEYCLOAK_DIR_LS:: $(ls $DATASTORE_KEYCLOAK_DIR)"
docker run -w /opt/keycloak \
-v "$HOST_DATASTORE_KEYCLOAK_DIR":"/opt/keycloak" \
--entrypoint bash \
"$DOCKER_BASE_IMAGE" -c "
export KC_METRICS_ENABLED=true
export KC_FEATURES=token-exchange
export KC_DB=postgres
keytool -genkeypair -storepass password \
-storetype PKCS12 -keyalg RSA \
-keysize 2048 -dname 'CN=$domain' \
-alias server -ext 'SAN:c=DNS:$domain,IP:$ip_host' \
-keystore conf/server.keystore || exit 1
echo 'Generated key'
/opt/keycloak/bin/kc.sh build
" || {
rmdir "$DATASTORE_KEYCLOAK_DIR/conf" 2>/dev/null
rmdir "$DATASTORE_KEYCLOAK_DIR" 2>/dev/null
return 1
}
}

View File

@@ -1,24 +0,0 @@
data-resources:
- /opt/keycloak
default-options:
uses:
web-proxy:
#constraint: required | recommended | optional
#auto: pair | summon | none ## default: pair
constraint: required
auto: pair
solves:
proxy: "Public access"
default-options:
target: !var-expand ${MASTER_BASE_SERVICE_NAME}:8080
postgres-database:
#constraint: required | recommended | optional
#auto: pair | summon | none ## default: pair
constraint: required
auto: summon
solves:
database: "main storage"
default-options:

View File

@@ -0,0 +1,17 @@
#!/bin/bash
set -e
DOMAIN=$(relation-get domain) || {
echo "Failed to get domain"
exit 1
}
config-add "\
services:
$MASTER_BASE_SERVICE_NAME:
environment:
N8N_HOST: \"${DOMAIN}\"
WEBHOOK_URL: \"https:\/\/${DOMAIN}\"
"

View File

@@ -1,4 +1,4 @@
docker-image: docker.n8n.io/n8nio/n8n:1.23.0
docker-image: docker.0k.io/n8n:1.45.1
uses:
postgres-database:
@@ -22,6 +22,15 @@ uses:
proxy: "Public access"
default-options:
target: !var-expand ${MASTER_BASE_SERVICE_NAME}:5678
apache-custom-rules:
- !var-expand |
## Use RewriteEngine to handle WebSocket connection upgrades
RewriteEngine On
RewriteCond %{HTTP:Upgrade} ^websocket$ [NC]
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteRule /(.*)\$ ws://${MASTER_BASE_SERVICE_NAME}:5678/\$1 [P,L]
backup:
constraint: recommended
auto: pair

View File

@@ -1,6 +1,6 @@
# -*- ispell-local-dictionary: "english" -*-
* Info
* Info
From: https://docs.getoutline.com/s/hosting/doc/docker-7pfeLP5a8t
@@ -12,8 +12,9 @@ Config info: https://github.com/outline/outline/blob/main/.env.sample
Odoo config: if you configure odoo OIDC connector, the callback url
should be like this : https://<YOUR_OUTLINE>:443/auth/oidc.callback
Requires a =smtp-server= provider to be functional, you can use
=smtp-stub= charm to provide information to externally managed =SMTP=.
#Requires a =smtp-server= provider to be functional, you can use
#=smtp-stub= charm to provide information to externally managed =SMTP=.
#+begin_src yaml
outline:
@@ -26,16 +27,20 @@ outline:
oidc-user-info-uri: #the user info uri of your OIDC provider
oidc-logout-uri: #the login uri of your OIDC provider
smtp-stub:
options:
host: smtp.myhost.com
port: 465
connection-security: "ssl/tls"
auth-method: password #IMPORTANT: if not present login password doesn’t work
login: myuser
password: myp4ssw0rd
#smtp-stub:
# options:
# host: smtp.myhost.com
# port: 465
# connection-security: "ssl/tls"
# auth-method: password #IMPORTANT: if not present login password doesn’t work
# login: myuser
# password: myp4ssw0rd
#+end_src
** Odoo 14
We monkey-patch odoo in order to make it work, be sure to use latest version in 14.0 of galicea openIDConnection module
* Building a new image
@@ -45,52 +50,29 @@ We use the official image with an added patch due to 2 bugs:
Note that a PR was pushed with a fix on the first bug. But this was not yet tested.
These fix are on 0.76.0
The fix are on 1.6.1
** First fix
** Fix
We need to add "url.port = '';" in ~build/server/middlewares/passport.js~ to remove the port. Note that this is a bad fix but works for our setup.
#+begin_src bash
IMAGE=docker.0k.io/outline:0.76.0-elabore
echo 'apk add patch bash' | dupd -u "$IMAGE" -- -u 1
cat <<'EOF1' | dupd -u "$IMAGE" -- -u 0
patch -p 1 <<'EOF2'
--- a/build/server/middlewares/passport.js
+++ b/build/server/middlewares/passport.js
@@ -40,6 +40,7 @@
const requestHost = ctx.get("host");
const url = new URL("".concat(reqProtocol, "://").concat(requestHost).concat(redirectUrl));
url.host = host;
+ url.port = '';
return ctx.redirect("".concat(url.toString()).concat(hasQueryString ? "&" : "?", "notice=").concat(notice));
}
if (_env.default.isDevelopment) {
EOF2
EOF1
#+end_src
** Second fix
Upon calling "/oidc" url, outline will return "Set-Cookie" header
with a "domain:" value that is incorrect (still the inner docker
Upon calling "/oidc" url, outline will return "Set-Cookie" header
with a "domain:" value that is incorrect (still the inner docker
domain: "outline" instead of the outer proxy domain from the frontend.)
Fortunately we can simply remove the value "domain" from the cookie by
Fortunately we can simply remove the value "domain" from the cookie by
commenting only 2 lines in ~build/server/utils/passport.js~.
The patches will change the "build/" files, so this is a very temporary and brittle fix.
#+begin_src bash
IMAGE=docker.0k.io/outline:0.76.0-elabore
IMAGE=docker.0k.io/outline:1.6.1-elabore
echo 'apt update && apt install patch' | dupd -u "$IMAGE" -- -u 0
cat <<'EOF1' | dupd -u "$IMAGE" -- -u 0
patch -p 1 <<'EOF2'
--- a/build/server/utils/passport.js.orig
+++ b/build/server/utils/passport.js
@@ -37,7 +37,7 @@
@@ -56,7 +56,7 @@
const state = buildState(host, token, client);
ctx.cookies.set(this.key, state, {
expires: (0, _dateFns.addMinutes)(new Date(), 10),
@@ -99,7 +81,7 @@ patch -p 1 <<'EOF2'
});
callback(null, token);
});
@@ -53,7 +53,7 @@
@@ -73,7 +73,7 @@
// Destroy the one-time pad token and ensure it matches
ctx.cookies.set(this.key, "", {
expires: (0, _dateFns.subMinutes)(new Date(), 1),

View File

@@ -47,6 +47,7 @@ oidc_logout_uri=$(options-get oidc-logout-uri) || exit 1
init-config-add "
$SERVICE_NAME:
restart: unless-stopped
volumes:
- $SERVICE_DATASTORE:/var/lib/outline/data
environment:
@@ -62,12 +63,12 @@ $SERVICE_NAME:
OIDC_LOGOUT_URI: \"$oidc_logout_uri\"
OIDC_SCOPES: \"openid\"
OIDC_USERNAME_CLAIM: \"preferred_username\"
OIDC_DISPLAY_NAME: \"OpenID Connect\"
NODE_ENV: \"production\"
LOG_LEVEL: \"debug\"
FORCE_HTTPS: \"false\"
FILE_STORAGE: \"local\"
#DEVELOPMENT_UNSAFE_INLINE_CSP: \"true\"
DEBUG: \"http\"
#DEBUG: \"http\"
"

View File

@@ -13,9 +13,9 @@ services:
$MASTER_BASE_SERVICE_NAME:
environment:
SMTP_USERNAME: \"$user\"
SMTP_PASS: \"${password//\$/\$\$}\"
SMTP_PASSWORD: \"${password//\$/\$\$}\"
SMTP_HOST: \"$host\"
SMTP_PORT: \"$port\"
#SMTP_SECURE: \"false\"
SMTP_FROM_EMAIL: \"$user\"
"

View File

@@ -1,4 +1,4 @@
docker-image: docker.0k.io/outline:0.76.0-elabore
docker-image: docker.0k.io/outline:0.83.0-elabore
uses:
postgres-database:
@@ -11,6 +11,8 @@ uses:
default-options:
extensions:
- uuid-ossp
- unaccent
- pg_trgm
redis-database:
constraint: required
auto: summon
@@ -30,6 +32,15 @@ uses:
proxy: "Public access"
default-options:
target: !var-expand ${MASTER_BASE_SERVICE_NAME}:3000
apache-custom-rules:
- !var-expand |
## Use RewriteEngine to handle WebSocket connection upgrades
RewriteEngine On
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteRule /(.*)\$ ws://${MASTER_BASE_SERVICE_NAME}:3000/\$1 [P,L]
backup:
constraint: recommended
auto: pair

7
plausible/README.org Normal file
View File

@@ -0,0 +1,7 @@
# -*- ispell-local-dictionary: "english" -*-
* Info
From: https://github.com/plausible/community-edition/
* Usage

View File

@@ -0,0 +1,14 @@
#!/bin/bash
set -e
config-add "\
services:
$MASTER_BASE_SERVICE_NAME:
environment:
CLICKHOUSE_DATABASE_URL: http://$TARGET_SERVICE_NAME:8123/$TARGET_SERVICE_NAME
"
info "Configured $SERVICE_NAME code for $TARGET_SERVICE_NAME access."

27
plausible/hooks/init Executable file
View File

@@ -0,0 +1,27 @@
#!/bin/bash
SECRET_KEY_BASE="$SERVICE_DATASTORE"/secret-key
SHARE_DIR="$SERVICE_DATASTORE"/var/lib/plausible
mkdir -p $SHARE_DIR
uid=$(docker_get_uid "$SERVICE_NAME" "plausible")
if ! [ -f "$SECRET_KEY_BASE" ]; then
info "Generating secret key"
mkdir -p "${SECRET_KEY_BASE%/*}"
umask 077
openssl rand -base64 64 > "$SECRET_KEY_BASE"
else
info "Using existing secret key"
fi
secret_key_base=$(cat "$SECRET_KEY_BASE")
init-config-add "
$SERVICE_NAME:
environment:
SECRET_KEY_BASE: \"$secret_key_base\"
"
chown -v "$uid" "$SHARE_DIR"

View File

@@ -6,12 +6,12 @@ PASSWORD="$(relation-get password)"
USER="$(relation-get user)"
DBNAME="$(relation-get dbname)"
config-add "\
services:
$MASTER_BASE_SERVICE_NAME:
environment:
KC_DB_URL: \"jdbc:postgresql://$MASTER_TARGET_SERVICE_NAME:5432/$DBNAME\"
KC_DB_USERNAME: \"$USER\"
KC_DB_PASSWORD: \"$PASSWORD\"
KC_DB: \"postgres\"
DATABASE_URL: postgres://$USER:$PASSWORD@$TARGET_SERVICE_NAME:5432/$DBNAME
"
info "Configured $SERVICE_NAME code for $TARGET_SERVICE_NAME access."

View File

@@ -0,0 +1,22 @@
#!/bin/bash
set -e
host=$(relation-get host) || exit 1
port=$(relation-get port) || exit 1
user=$(relation-get login) || exit 1
password="$(relation-get password)" || exit 1
config-add "\
services:
$MASTER_BASE_SERVICE_NAME:
environment:
SMTP_USER_NAME: \"$user\"
SMTP_USER_PWD: \"${password//\$/\$\$}\"
SMTP_HOST_ADDR: \"$host\"
SMTP_HOST_PORT: \"$port\"
SMTP_HOST_SSL_ENABLE: \"true\"
MAILER_EMAIL: \"$user\"
"

View File

@@ -0,0 +1,16 @@
#!/bin/bash
set -e
DOMAIN=$(relation-get domain) || {
echo "Failed to get domain"
exit 1
}
config-add "\
services:
$MASTER_BASE_SERVICE_NAME:
environment:
BASE_URL: \"https:\/\/${DOMAIN}\"
"

58
plausible/metadata.yml Normal file
View File

@@ -0,0 +1,58 @@
docker-image: docker.0k.io/plausible:3.0.1
#docker-image: ghcr.io/plausible/community-edition:v3.0.1
data-resources:
- /var/lib/plausible
docker-compose:
entrypoint: sh -c "/entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run"
#entrypoint: sh -c "/entrypoint.sh run"
uses:
event-db:
#constraint: required | recommended | optional
#auto: pair | summon | none ## default: pair
constraint: required
auto: summon
solves:
database: "event db"
postgres-database:
#constraint: required | recommended | optional
#auto: pair | summon | none ## default: pair
constraint: required
auto: summon
solves:
database: "main storage"
default-options:
extensions:
- citext
smtp-server:
constraint: required
auto: summon
solves:
proxy: "Public access"
web-proxy:
#constraint: required | recommended | optional
#auto: pair | summon | none ## default: pair
constraint: recommended
auto: pair
solves:
proxy: "Public access"
default-options:
target: !var-expand ${MASTER_BASE_SERVICE_NAME}:8000
apache-custom-rules:
- !var-expand |
ProxyPreserveHost On
#Set web sockets
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/(live/websocket)$ ws://${MASTER_BASE_SERVICE_NAME}:8000/\$1 [P,L]
backup:
constraint: recommended
auto: pair
solves:
backup: "Automatic regular backup"
default-options: