big update

This commit is contained in:
adrian 2025-10-31 18:49:12 +01:00
parent 8992a9cdb6
commit 868f2046ce
165 changed files with 7726 additions and 769 deletions

View File

@ -210,6 +210,7 @@ section "Configuring new system"
uuid=$(blkid | grep "$root_device" | cut -d ' ' -f 2)
line_in_file "$uuid / ext4 errors=remount-ro 0 1" "$mnt/etc/fstab"
line_in_file "proc /proc proc defaults" "$mnt/etc/fstab"
tune2fs -O ^orphan_file "$root_device" #2025-04 To fix e2fsck incompatibility
# TODO set noauto to /boot if needed
# Set hostname
@ -321,10 +322,10 @@ fi
if [ "$arg_test" != "false" ] ; then
section "Testing installed system"
run qemu-system-x86_64 -m 1024M "$boot_device"
fi
#if [ "$arg_test" != "false" ] ; then
# section "Testing installed system"
# run qemu-system-x86_64 -m 1024M "$boot_device"
#fi
echo "To test the system with qemu type:"
echo "qemu-system-x86_64 -m 1024M '$boot_device'"

View File

@ -1,9 +1,13 @@
[shlago]
#max.jean-cloud.org
raku.jean-cloud.org
#cheri.jean-cloud.org
taillax.jean-cloud.org
[servers]
montbonnot.jean-cloud.org
#max.jean-cloud.org
raku.jean-cloud.org
taillax.jean-cloud.org
izzo.jean-cloud.org
cheri.jean-cloud.org

View File

@ -110,3 +110,5 @@
##- deploy_all
# TODO
# journalctl --vacuum-size=500M

View File

@ -22,7 +22,7 @@ struct passwd * getUid(char *name) {
/* Run deploy as user */
int runServiceDeployment(char *service) {
int runServiceDeployment(char *service, char *exe) {
/* Set uid and gid */
struct passwd *p = getUid(service);
setgid(p->pw_gid);
@ -55,7 +55,7 @@ int runServiceDeployment(char *service) {
}
/* Execute DEPLOY_AS_SH */
if (execl("/bin/bash", "--noediting", "--noprofile", "--norc", "--", DEPLOY_AS_SH, service, (char *)NULL) == -1) {
if (execl("/bin/bash", "--noediting", "--noprofile", "--norc", "--", DEPLOY_AS_SH, service, exe, (char *)NULL) == -1) {
printf("Error exec %s\n", DEPLOY_AS_SH);
printf("%s\n", strerror(errno));
exit(1);
@ -84,16 +84,21 @@ int validate (char *s) {
int main(int argc, char *argv[] )
{
if ( argc != 2) {
printf("usage: %s <service-name>\n",argv[0]);
if ( argc != 2 && argc != 3) {
printf("usage: %s <service-name> [exe]\n",argv[0]);
exit(1);
}
if (validate(argv[1]) != 0) {
} else if (validate(argv[1]) != 0) {
printf("Bad service name\n");
exit(1);
} else if (argc == 2 ){
runServiceDeployment(argv[1], "");
} else if (argc == 3) {
if (validate(argv[2]) != 0) {
printf("Invalid exec name\n");
exit(1);
}
runServiceDeployment(argv[1], argv[2]);
}
runServiceDeployment(argv[1]);
return 0;
}

View File

@ -54,9 +54,10 @@ cd "/docker/$service"
###############################################################################
if "$deploy" ; then
run mkdir -p "$DATA_DIR" "$HTTP_DIR"
run chown $uid "$DATA_DIR" "$HTTP_DIR"
run mkdir -p "$DATA_DIR" "$HTTP_DIR" "$TMP_DIR"
run chown $uid "$DATA_DIR" "$HTTP_DIR" "$TMP_DIR"
run chmod 751 "$DATA_DIR"
run chmod 751 "$TMP_DIR"
run chown $uid:www-data -R "$HTTP_DIR"
if [ -d "$SECRET_DIR" ] ; then
run chown $uid "$SECRET_DIR" -R

View File

@ -1,14 +1,24 @@
#!/bin/bash
set -euo pipefail
if [ "$#" -ne 1 ] || [ -z "$1" ] ; then
echo "Usage: $0 <service_name>"
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ] || [ -z "$1" ] ; then
echo "Usage: $0 <service_name> [exe]"
echo "script can be empty"
exit 1
fi
service="$1"
exe=""
if [ "$#" -eq 2 ] ; then
exe="$2"
fi
if [ -z "$exe" ] ; then
user_file="/docker/$service/deploy_user.sh"
else
user_file="/docker/$service/$exe"
fi
user_file="/docker/$service/deploy_user.sh"
if [ ! -f "$user_file" ] ; then
echo "No such file: $user_file"

View File

@ -29,6 +29,13 @@ here="$(where 'follow_links')"
[ ! -f /data/mounted ] && die "/data is not mounted"
lock=/tmp/shlaguernetes/lock
mkdir -p /tmp/shlaguernetes
[ -e "$lock" ] && die "Lockfile is present"
touch "$lock"
clean "rm $lock"
###############################################################################
# Nginx preparation
###############################################################################
@ -67,13 +74,13 @@ while IFS=';' read -r id username service target
do
echo -n "$service -> "
[ ! -d "/docker/$service" ] && die "/docker/$service directory not found"
[ ! -d "/docker/$service" ] && echo "/docker/$service directory not found" && continue
# Check if service target is localhost
[[ "$(getent hosts $target)" != "::1 "* ]] && echo 'Not here' && continue
[[ "$(getent hosts $target)" != "::1 "* ]] && continue
echo "Deploying"
deploy_service.sh "$service" "noreload" &>"$logdir/deploy.$service.$(date +%Y-%m-%d.%Hh-%M-%S)" &
deploy_service.sh "$service" "noreload" >"$logdir/deploy.$service.$(date +%Y-%m-%d.%Hh-%M-%S)" 2>&1 &
if [ "$?" -ne 0 ] ; then
failed="$failed $service"

View File

@ -18,17 +18,16 @@ fi
# Look in both cert directories
for dir in "$dns_certs_path" "$http_certs_path" ; do
name="$(ls "$dir" | grep "^$service\(-[0-9]\{4\}\)\?$")" || true
if [ -z "$name" ] ; then
if [ ! -d "$dir/$service" ] ; then
if $verbose ; then
echo "Service $service have no certificate in $dir" >&2
fi
elif [ ! -e "$dir/$name/fullchain.pem" ] ; then
elif [ ! -e "$dir/$service/fullchain.pem" ] ; then
if $verbose ; then
echo "Service $service have no cert in dir $dir" >&2
echo "Service $service have no fullchain.pem in dir $dir" >&2
fi
else
echo "$dir/$name"
echo "$dir/$service"
exit 0
fi
done

View File

@ -27,6 +27,7 @@ do
line_in_file "HTTP_DIR='/srv/http/$service'" "$dir/.env"
line_in_file "DATA_DIR='/data/$service'" "$dir/.env"
line_in_file "TMP_DIR='/tmp/$service'" "$dir/.env"
line_in_file "SECRET_DIR='/data/secrets/$service'" "$dir/.env"
line_in_file "DOCKER_DIR='$dir'" "$dir/.env"
line_in_file "JC_SERVICE='$service'" "$dir/.env"
@ -35,6 +36,9 @@ do
line_in_file "USER='$username'" "$dir/.env"
line_in_file "JC_ID='$id'" "$dir/.env"
# This one must be after the others
line_in_file "JC_DOMAINS='$(extract_domain_nginx_conf.sh "$dir/nginx_server.conf" | template.sh "$dir/.env" | tr ' ' '\n' | sort -u | tr '\n' ' ' | xargs)'" "$dir/.env"
cert="$(findcert.sh "$service")" || true
if [ -n "$cert" ] ; then
line_in_file "JC_CERT='$cert'" "$dir/.env"

View File

@ -74,7 +74,7 @@ if [ -d .git ] ; then
git reflog expire --expire=now --all
if "$be_aggressive" ; then
git gc --prune=now --aggressive
elsels
else
git gc --prune=now
fi
else

View File

@ -38,6 +38,7 @@ while IFS='=' read key value ; do
webdav_user="$(echo "$url" |sed 's#.*/s/##')"
webdav_pass="$(rclone obscure "$password")"
echo rclone sync --config=/notfound --webdav-url="$webdav_url" --webdav-user="$webdav_user" --webdav-pass="$webdav_pass" --webdav-vendor=nextcloud :webdav: "$destination"
rclone sync --config=/notfound --webdav-url="$webdav_url" --webdav-user="$webdav_user" --webdav-pass="$webdav_pass" --webdav-vendor=nextcloud :webdav: "$destination"
# Go to website

View File

@ -7,8 +7,18 @@ if [ "$#" -ge 1 ] && [ -n "$1" ] ; then
server="$1"
fi
while read domain; do
host "$domain" $server &>/dev/null
[ "$?" -eq 0 ] && echo "$domain"
first=true
while read line; do
for domain in $line ; do
host "$domain" $server &>/dev/null
if [ "$?" -eq 0 ] ; then
if "$first" ; then
first=false
else
echo -n ' '
fi
echo -n "$domain"
fi
done
done
exit 0

View File

@ -2,7 +2,7 @@
# tasks file for deploy_all
- name: "Check for secrets volume. Fail if not found"
include: "{{ item }}"
include_tasks: "{{ item }}"
with_first_found:
- files:
- secrets/mounted
@ -35,6 +35,9 @@
recursive: true
copy_links: true # This allows some bidouillage on the server
- name: Run init
command: init.sh
#- name: Add bind conf
# ansible.posix.synchronize:
# src: "{{ role_path }}/files/bind/"

View File

@ -0,0 +1,2 @@
DATA_DIR=/tmp/mock_data
NET=172.29.1

View File

@ -0,0 +1,43 @@
version: '3'
services:
db:
image: postgres:17-alpine
restart: unless-stopped
volumes:
- $DATA_DIR/db:/var/lib/postgresql/data
networks:
default:
ipv4_address: $NET.101
nextcloud:
image: nextcloud:29-fpm-alpine
volumes:
- $DATA_DIR/app:/var/www/html
depends_on:
- db
restart: unless-stopped
networks:
default:
ipv4_address: $NET.100
redis:
image: redis:latest
volumes:
- /var/lib/redis:/data
command: redis-server --appendonly yes
restart: unless-stopped
networks:
default:
ipv4_address: $NET.103
deploy:
resources:
limits:
cpus: '0.50'
memory: 2000M
networks:
default:
ipam:
config:
- subnet: $NET.0/24

View File

@ -0,0 +1 @@
docker-compose exec -u www-data nextcloud php occ maintenance:mode --on

View File

@ -0,0 +1,197 @@
# inspired from
# https://docs.nextcloud.com/server/28/admin_manual/installation/nginx.html#nextcloud-in-the-webroot-of-nginx
# 2024 02 11
# Set the `immutable` cache control options only for assets with a cache busting `v` argument
map $arg_v $asset_immutable {
"" "";
default ", immutable";
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name $JC_SERVICE www.$JC_SERVICE;
# Path to the root of your installation
root $DATA_DIR/app;
# Use Mozilla's guidelines for SSL/TLS settings
# https://mozilla.github.io/server-side-tls/ssl-config-generator/
ssl_certificate $JC_CERT/fullchain.pem;
ssl_certificate_key $JC_CERT/privkey.pem;
#limit_req zone=defaultlimit burst=500 nodelay;
# Prevent nginx HTTP Server Detection
server_tokens off;
# HSTS settings
# WARNING: Only add the preload option once you read about
# the consequences in https://hstspreload.org/. This option
# will add the domain to a hardcoded list that is shipped
# in all major browsers and getting removed from this list
# could take several months.
#add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always;
# set max upload size and increase upload timeout:
client_max_body_size 10G;
client_body_timeout 300s;
fastcgi_buffers 64 4K;
# Enable gzip but do not remove ETag headers
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
# Pagespeed is not supported by Nextcloud, so if your server is built
# with the `ngx_pagespeed` module, uncomment this line to disable it.
#pagespeed off;
# The settings allows you to optimize the HTTP2 bandwidth.
# See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/
# for tuning hints
client_body_buffer_size 512k;
# HTTP response headers borrowed from Nextcloud `.htaccess`
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "noindex, nofollow" always;
add_header X-XSS-Protection "1; mode=block" always;
# Remove X-Powered-By, which is an information leak
fastcgi_hide_header X-Powered-By;
# Set .mjs and .wasm MIME types
# Either include it in the default mime.types list
# and include that list explicitly or add the file extension
# only for Nextcloud like below:
include mime.types;
types {
text/javascript mjs;
}
# Specify how to handle directories -- specifying `/index.php$request_uri`
# here as the fallback means that Nginx always exhibits the desired behaviour
# when a client requests a path that corresponds to a directory that exists
# on the server. In particular, if that directory contains an index.php file,
# that file is correctly served; if it doesn't, then the request is passed to
# the front-end controller. This consistent behaviour means that we don't need
# to specify custom rules for certain paths (e.g. images and other assets,
# `/updater`, `/ocs-provider`), and thus
# `try_files $uri $uri/ /index.php$request_uri`
# always provides the desired behaviour.
index index.php index.html /index.php$request_uri;
# Rule borrowed from `.htaccess` to handle Microsoft DAV clients
location = / {
if ( $http_user_agent ~ ^DavClnt ) {
return 302 /remote.php/webdav/$is_args$args;
}
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# Make a regex exception for `/.well-known` so that clients can still
# access it despite the existence of the regex rule
# `location ~ /(\.|autotest|...)` which would otherwise handle requests
# for `/.well-known`.
location ^~ /.well-known {
# The rules in this block are an adaptation of the rules
# in `.htaccess` that concern `/.well-known`.
location = /.well-known/carddav { return 301 /remote.php/dav/; }
location = /.well-known/caldav { return 301 /remote.php/dav/; }
location /.well-known/acme-challenge { try_files $uri $uri/ =404; }
location /.well-known/pki-validation { try_files $uri $uri/ =404; }
# Let Nextcloud's API for `/.well-known` URIs handle all other
# requests by passing them to the front-end controller.
return 301 /index.php$request_uri;
}
# Rules borrowed from `.htaccess` to hide certain paths from clients
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; }
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; }
# Ensure this block, which passes PHP files to the PHP process, is above the blocks
# which handle static assets (as seen below). If this block is not declared first,
# then Nginx will encounter an infinite rewriting loop when it prepends `/index.php`
# to the URI, resulting in a HTTP 500 error response.
location ~ \.php(?:$|/) {
# Required for legacy support
rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
set $path_info $fastcgi_path_info;
try_files $fastcgi_script_name =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info;
fastcgi_param HTTPS on;
fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice
fastcgi_param front_controller_active true; # Enable pretty urls
fastcgi_pass $NET.100:9000;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
fastcgi_max_temp_file_size 0;
}
# Serve static files
location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map|ogg|flac)$ {
try_files $uri /index.php$request_uri;
# HTTP response headers borrowed from Nextcloud `.htaccess`
add_header Cache-Control "public, max-age=15778463$asset_immutable";
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "noindex, nofollow" always;
add_header X-XSS-Protection "1; mode=block" always;
access_log off; # Optional: Don't log access to assets
}
location ~ \.woff2?$ {
try_files $uri /index.php$request_uri;
expires 7d; # Cache-Control policy borrowed from `.htaccess`
access_log off; # Optional: Don't log access to assets
}
# Rule borrowed from `.htaccess`
location /remote {
return 301 /remote.php$request_uri;
}
location / {
try_files $uri $uri/ /index.php$request_uri;
}
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
proxy_cache_path /var/www/cache levels=1:2 keys_zone=my-cache:8m max_size=1000m inactive=600m;
proxy_temp_path /var/www/cache/tmp;

View File

@ -5,8 +5,6 @@ services:
environment:
UID: 33
MOUNT: /
ports:
- "2229:2229"
volumes:
- /tmp/uwsgi/$JC_SERVICE:/tmp/uwsgi
- $DATA_DIR/app/assets:/usr/src/app/assets

View File

@ -3,7 +3,7 @@ server {
listen [::]:443 ssl http2;
ssl_certificate $JC_CERT/fullchain.pem;
ssl_certificate_key $JC_CERT/privkey.pem;
server_name $JC_SERVICE benevoles.karnaval.fr;
server_name $JC_SERVICE;
root $DATA_DIR/app/assets;

View File

View File

@ -0,0 +1,47 @@
version: '3'
services:
app:
# Ce nom dimage tout gez est en fait la branche main de https://git.jean-cloud.net/benevoles/custom-karna
image: jeancloud/site-benevole:debian-master
environment:
UID: 33
MOUNT: /
ports:
- "2229:2229"
volumes:
- /tmp/uwsgi/$JC_SERVICE:/tmp/uwsgi
- $DATA_DIR/app/assets:/usr/src/app/assets
- $DATA_DIR/app/media:/usr/src/app/media
- $DATA_DIR/app/local_settings.py:/usr/src/app/site_benevole/local_settings.py
- $DATA_DIR/app/plugins.toml:/usr/src/app/site_benevole/plugins.toml
- $DATA_DIR/app/.plugins.sqlite3:/usr/src/app/site_benevole/.plugins.sqlite3
restart: unless-stopped
networks:
default:
ipv4_address: $NET.100
redis:
image: redis
networks:
default:
ipv4_address: $NET.102
db:
image: postgres:16.1-alpine
env_file: $DATA_DIR/postgres.env
environment:
POSTGRES_USER: benevoles
POSTGRES_DB: benevoles
volumes:
- $DATA_DIR/db:/var/lib/postgresql/data
networks:
default:
ipv4_address: $NET.101
networks:
default:
ipam:
config:
- subnet: $NET.0/24

View File

@ -0,0 +1,55 @@
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate $JC_CERT/fullchain.pem;
ssl_certificate_key $JC_CERT/privkey.pem;
server_name $JC_SERVICE benevoles.karnaval.fr;
root $DATA_DIR/app/assets;
gzip on;
gzip_static on;
gzip_types application/javascript image/* text/css application/font-woff application/font-woff2;
gunzip on;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_buffer_size 4k;
client_max_body_size 4M;
location / {
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi/$JC_SERVICE/uwsgi.sock;
}
location = /favicon.ico {
root $DATA_DIR/assets/;
}
location = /favicon-admin.ico {
root $DATA_DIR/assets/;
}
location /assets/ {
alias $DATA_DIR/app/assets/;
access_log off;
sendfile on;
tcp_nopush on;
sendfile_max_chunk 1m;
keepalive_timeout 65;
location ~* \.(jpg|jpeg|png|gif|ico|woff|woff2)$ {
access_log off;
expires 5d;
}
}
location /media/ {
alias $DATA_DIR/app/media/;
access_log off;
sendfile on;
tcp_nopush on;
sendfile_max_chunk 1m;
keepalive_timeout 65;
}
}

View File

@ -2,4 +2,4 @@
set -euo pipefail
# Update git repo
git_update.sh -b sale -d "$HTTP_DIR" "$GIT_SOURCE_REPO"
git_update.sh -r sale -d "$HTTP_DIR" "$GIT_SOURCE_REPO"

View File

@ -0,0 +1,55 @@
#!/bin/bash
set -euo pipefail
# Add ssh fingerprint
if [ ! -e ~/.ssh/known_hosts ] ; then
mkdir -p ~/.ssh
ssh-keyscan -p 22 gitlab.com > ~/.ssh/known_hosts
cp "$SECRET_DIR/gitlab-deploy.sshprivkey" ~/.ssh/id_rsa
fi
new_content=false
# Clone if needed
if [ ! -d "$DATA_DIR/core" ] ; then
cd "$DATA_DIR"
git clone git@gitlab.com:omaradio/core.git
cd core
new_content=true
else
cd "$DATA_DIR/core"
fi
# Set mtime of last modifying commit
gitmtim(){ local f;for f;do touch -d @0`git log --pretty=%at -n1 -- "$f"` "$f"; done;}
# Loop eche branch
for branch in dev recette ; do
git checkout -f "$branch"
# Check for new stuff
if ! git pull | grep -q 'Already up to date.' ; then
new_content=true
fi
# Clean repo
git clean -dfx
# Create bonus if needed
dest="$DATA_DIR/bonus-$branch"
if "$new_content" || [ ! -d $dest ] ; then
# Set git mtime for bonus files
cd "$DATA_DIR/core/"
for bonusdir in $(find "$DATA_DIR/core/radioDemo/" -type d -name 'importBonus*') ; do
gitmtim $(find "$bonusdir")
done
echo "Creating bonus to $dest"
mkdir -p "$dest"
cd "$DATA_DIR/core/radioDemo/"
./cfg_local/scripts/create_bonuses.sh "$DATA_DIR/core/radioDemo" "$dest"
fi
done
echo "OK. Tous les bonus sont générés."

View File

@ -0,0 +1,21 @@
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
ssl_certificate $JC_CERT/fullchain.pem;
ssl_certificate_key $JC_CERT/privkey.pem;
server_name $JC_SERVICE www.$JC_SERVICE;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'none';frame-ancestors 'none'; script-src 'self'; img-src 'self'; font-src 'self'; object-src 'none'; style-src 'self'; base-uri 'self'; form-action 'self';" always;
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options SAMEORIGIN always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header Permissions-Policy "geolocation='none';midi='none';notifications='none';push='none';sync-xhr='https://mailer.jean-cloud.net';microphone='none';camera='none';magnetometer='none';gyroscope='none';speaker='self';vibrate='none';fullscreen='self';payment='none';";
location / {
default_type text/html;
return 500 '<h1>Erreur du service</h1><p>Ce service nest pas accessible actuellement. Si cela nest pas normal prévenez-nous à cette adresse : contact@jean-cloud.net</p><p>Merci ! :)</p>';
}
}

View File

@ -0,0 +1 @@
SERVERS="izzo.jean-cloud.org raku.jean-cloud.org montbonnot.jean-cloud.org"

View File

@ -1,18 +1,45 @@
#!/bin/bash
if [ "$#" -ne 2 ] ; then
echo "Usage: $0 <service_name> <workdir>" >&2
if [ "$#" -ne 4 ] ; then
echo "Usage: $0 <service_name> <workdir> <cert_dir> <rfc2136_file>" >&2
exit 1
fi
service="$1"
workdir="$2"
certs_dir="$3"
rfc2136_file="$4"
certbotopt="--non-interactive --config-dir $certs_dir --work-dir $workdir/work --logs-dir $workdir/logs --agree-tos -m contact@jean-cloud.org"
nginxfile="/docker/$service/nginx_server.conf"
if [ -f "$nginxfile" ] ; then
nginxdomains="$(extract_domain_nginx_conf.sh "$nginxfile" | template.sh "/docker/$service/.env")"
domains="$(echo "$nginxdomains" | tr ' ' '\n' | sort -u | resolvable.sh ns.jean-cloud.org | sed -z -e 's/\n$//' -e 's/\n/ -d /g' )"
[ -z "$domains" ] && exit 0
echo "--------------- -d $domains"
certbot certonly --config-dir "$DATA_DIR/certs" --work-dir "$workdir/work" --logs-dir "$workdir/logs" --agree-tos -m contact@jean-cloud.org -n --cert-name "$service" --dns-rfc2136 --dns-rfc2136-credentials "$DATA_DIR/rfc2136.ini" -d $domains
. /docker/$service/.env
echo "== acme for $service"
[ -z "$JC_DOMAINS" ] && exit 0
domains="$(echo "$JC_DOMAINS" | resolvable.sh ns.jean-cloud.org)"
#domains="$JC_DOMAINS"
[ -z "$domains" ] && exit 0
# Detect letsencrypt duplicates
if ls "$certs_dir/live/" | grep -q "^$service-" ; then
echo "letsencrypt deplucate found for '$service'"
exit 1
fi
if [ -e "$certs_dir/live/$service/cert.pem" ] ; then
echo Cert already exists
current_domains="$(openssl x509 -text -in "$certs_dir/live/$service/cert.pem" | grep 'DNS:' | sed -e 's/, /\n/g' -e 's/DNS://g' -e 's/ //g' | sort -u | tr '\n' ' ' | sed 's/ $//' )"
if [ "$current_domains" = "$domains" ] ; then
echo "Existing cert got the same domains, preserving"
exit 0
else
echo "New domains, removing old cert for $service"
certbot delete $certbotopt --cert-name "$service" --reason superseded
fi
fi
[ -z "$domains" ] && exit 0
domains="$(echo -n "$domains" | tr '\n' ' ' | sed -e 's/ / -d /g' )"
echo "--------------- -d $domains"
certbot certonly $certbotopt --cert-name "$service" --dns-rfc2136 --dns-rfc2136-credentials "$rfc2136_file" -d $domains

View File

@ -7,6 +7,24 @@ set -u
# For some variables
. /etc/jeancloud.env
# Add the servers to the known_hosts file
mkdir -p "$DATA_DIR/fingerprints"
for server in $SERVERS ; do
fingerprint_file="$DATA_DIR/fingerprints/$server.fingerprint"
if [ ! -e "$fingerprint_file" ] ; then
ssh-keyscan -p 45985 "$server" > "$fingerprint_file"
fi
done
cat "$DATA_DIR"/fingerprints/*.fingerprint > ~/.ssh/known_hosts
# Test dns server is up
if [ -z "$(echo 'ns.jean-cloud.org' | resolvable.sh ns.jean-cloud.org)" ] ; then
echo 'Dns server not working'
exit 1
fi
# Test secret presence
[ ! -f "$DATA_DIR/rfc2136.ini" ] && echo "$0 Missing file '$DATA_DIR/rfc2136.ini'" && exit 1
@ -14,26 +32,25 @@ export workdir="$(mktemp -d)"
mkdir -p "$workdir/{work,logs}"
echo "Renew existing certs"
certbot renew --config-dir "$DATA_DIR/certs" --logs-dir "$workdir/logs" --dns-rfc2136 --dns-rfc2136-credentials "$DATA_DIR/rfc2136.ini" --work-dir "$workdir" || true
echo "For each service, read all possible domains"
while IFS=';' read -r id username service target ; do
if [ -z "$service" ] ; then continue ; fi
if [ -d "$DATA_DIR/certs/live/$service" ] ; then
#echo "Already exists, thats a job for renew : $service"
continue
fi
#if [ -d "$DATA_DIR/certs/live/$service" ] ; then
# #echo "Already exists, thats a job for renew : $service"
# continue
#fi
# acme
"$DOCKER_DIR/acme-dns.sh" "$service" "$workdir"
"$DOCKER_DIR/acme-dns.sh" "$service" "$workdir" "$DATA_DIR/certs" "$DATA_DIR/rfc2136.ini"
done < <(grep -v '^#' "$servicefile")
echo "Renew existing certs"
certbot renew --config-dir "$DATA_DIR/certs" --logs-dir "$workdir/logs" --dns-rfc2136 --dns-rfc2136-credentials "$DATA_DIR/rfc2136.ini" --work-dir "$workdir" || true
echo "Push certs to other servers"
for srv in $(host -t TXT shlago.jean-cloud.org ns.jean-cloud.org | grep -Po 'descriptive text "\K[^"]+' | tr ',' ' ' | tr ' ' '\n') nougaro tetede montbonnot max raku izzo ; do
server="$srv.jean-cloud.org"
for srv in $SERVERS ; do
[ -n "$(grep "$server" /etc/hosts)" ] && continue
echo "-- $server"
rsync -avz -e "ssh -i '$DATA_DIR/certs.priv' -p 45985" "$DATA_DIR/certs" "dnscerts.jean-cloud.org@$server:$DATA_DIR/" || true

View File

@ -0,0 +1,2 @@
GIT_SOURCE_REPO="https://framagit.org/adrian-amaglio/ffcoinche.fr"

View File

@ -0,0 +1,5 @@
#!/bin/bash
set -euo pipefail
# Update git repo
git_update.sh -d "$HTTP_DIR" -r "${GIT_SOURCE_BRANCH:-main}" "$GIT_SOURCE_REPO"

View File

@ -0,0 +1,24 @@
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate $JC_CERT/fullchain.pem;
ssl_certificate_key $JC_CERT/privkey.pem;
server_name $JC_SERVICE www.$JC_SERVICE;
root $HTTP_DIR/public;
# Security headers
# We can create a file with the base security headers and include it.
# Will it be possible to overload them then ?
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'none';frame-ancestors 'none'; script-src 'unsafe-inline'; img-src *; font-src 'self'; object-src 'none'; style-src 'self'; base-uri 'self'; form-action 'self';" always;
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options SAMEORIGIN always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header Permissions-Policy "geolocation='none';midi='none';notifications='none';push='none';sync-xhr='https://mailer.jean-cloud.net';microphone='none';camera='none';magnetometer='none';gyroscope='none';speaker='self';vibrate='none';fullscreen='self';payment='none';";
location / {
index index.html;
try_files $uri $uri/ =404;
}
}

View File

@ -0,0 +1,32 @@
#!/bin/bash
wgif=omakipik
ip=10.100.101.254
run="ip netns exec $wgif"
# Create netns if needed
if ! ip netns | grep -q "$wgif" ; then
ip netns add "$wgif"
fi
# Create iface
if ! $run ip link | grep -q "$wgif" ; then
ip link add "$wgif" type wireguard
ip link set "$wgif" netns "$wgif"
fi
# Set ip
if ! $run ip -4 -o a | grep -q "$ip" ; then
$run ip a add "$ip" dev "$wgif"
fi
# Set route
if ! $run ip -4 -o r | grep -q "default dev $wgif" ; then
$run ip r add default dev "$wgif"
fi
# Up iface
$run ip link set up dev "$wgif"
# Load config
$run wg setconf "$wgif" "/etc/wireguard/$wgif.conf"

View File

@ -0,0 +1,38 @@
#!/bin/bash
set -euo pipefail
. .env
wgif="$1"
net="10.100.$JC_ID"
privfile="$DATA_DIR/wgif.wgprivatekey"
# Create key if doesnt exists
if [ ! -e "$privfile" ] ; then
wg genkey > "$privfile"
fi
# Print wg-quick config
echo "
[Interface]
PrivateKey = $(cat "$privfile")
ListenPort = $((51800+$JC_ID))
Address = $net.254/32
[Peer] # Adrian
PublicKey = p4/km7Rtl5IgYGw8OPIyE0/f8UoRbcMJwkVJ0Zyv/C8=
AllowedIPs = $net.253/32
[Peer] # Nico
PublicKey = jsXBs8tZn1sWT73xx3DWEdGAWv6SjfQ2TAxX+8pL6mU=
AllowedIPs = $net.252/32
[Peer] # Passerelle
PublicKey = ZTKOW5DE8jPO8oMh5hAw/c1MQSlUaVxInMPz9Zdwzwo=
AllowedIPs = $net.13/32,192.168.100.0/24
[Peer] # Debug
PublicKey = K9IpoUbjyN+42y0YG3OIwAPRBZcd92GnKfbYEj3RZ18=
AllowedIPs = $net.21/32
"

View File

@ -0,0 +1 @@
SFTP_USER=letourbillonRO

View File

@ -0,0 +1 @@
../sftp_jc/deploy.sh

View File

@ -0,0 +1 @@
../sftp_jc/deploy_user.sh

View File

@ -0,0 +1 @@
../sftp_jc/nginx_server.conf

View File

@ -0,0 +1,24 @@
#!/bin/bash
# The blackbox target file as it will be read by prometheus
blackbox=$DATA_DIR/all-targets.yml
echo '- targets:' > "$blackbox"
# Find each service and its target
while IFS=';' read -r _ _ service target
do
# Find all ips of this target
IFS=';' read -ra ips < <(grep "$target" /docker/servers.csv)
ips=("${ips[@]:6}")
[ -z "$ips" ] && continue
for ip in ${ips[@]}
do
# Monitor each ip the service must answer on
echo " - $service@$ip" >> "$blackbox"
done
done < <(grep -v '^#' /docker/services.csv)
echo "$blackbox"

View File

@ -0,0 +1,39 @@
version: '3.7'
services:
prometheus:
image: prom/prometheus
volumes:
- $DOCKER_DIR/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- $DATA_DIR/blackbox-targets.yml:/etc/prometheus/blackbox-targets.yml:ro
- $DATA_DIR/data:/prometheus
restart: unless-stopped
networks:
default:
ipv4_address: $NET.100
grafana:
image: grafana/grafana
volumes:
- $DOCKER_DIR/grafana.ini:/etc/grafana/grafana.ini
- $DATA_DIR/grafana/data:/var/lib/grafana
restart: unless-stopped
networks:
default:
ipv4_address: $NET.101
blackbox_exporter:
image: prom/blackbox-exporter
dns: 9.9.9.9
volumes:
- $DATA_DIR/blackbox-targets.yml:/config/blackbox-config.yml
restart: unless-stopped
networks:
default:
ipv4_address: $NET.102
networks:
default:
ipam:
config:
- subnet: $NET.0/24

View File

@ -0,0 +1,13 @@
[smtp]
enabled = true
host = mail.gandi.net:587
user = nepasrepondre@jean-cloud.org
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
password = ZMTX9B6VgsVvdbXSzC7Zp4ASj6DU6q22Zi7KnjXtGYHE7WmJBM3pkhW9Rcdx
;skip_verify = false
from_address = nepasrepondre@jean-cloud.org
from_name = Grafana
# EHLO identity in SMTP dialog (defaults to instance_name)
;ehlo_identity = dashboard.example.com

View File

@ -0,0 +1,326 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"description": "Monitor and set alerts for all the pings to your servers using blackbox exporter and prometheus.",
"editable": true,
"gnetId": 5990,
"graphTooltip": 0,
"id": 3,
"iteration": 1629329153476,
"links": [],
"panels": [
{
"alert": {
"alertRuleTags": {},
"conditions": [
{
"evaluator": {
"params": [
1
],
"type": "lt"
},
"operator": {
"type": "and"
},
"query": {
"params": [
"A",
"5m",
"now"
]
},
"reducer": {
"params": [],
"type": "sum"
},
"type": "query"
}
],
"executionErrorState": "alerting",
"for": "0m",
"frequency": "60s",
"handler": 1,
"message": "Server does not respond to ping!",
"name": "Server Status alert",
"noDataState": "no_data",
"notifications": []
},
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"links": []
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 24,
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 9,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 0,
"links": [],
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "8.0.6",
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "probe_success{job=\"ping\"}",
"format": "time_series",
"intervalFactor": 1,
"legendFormat": "{{instance}}",
"refId": "A"
}
],
"thresholds": [
{
"colorMode": "critical",
"fill": true,
"line": true,
"op": "lt",
"value": 1,
"visible": true
}
],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Server Status",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"decimals": 0,
"format": "none",
"label": "OK",
"logBase": 1,
"max": "1",
"min": "0",
"show": true
},
{
"decimals": null,
"format": "short",
"label": "",
"logBase": 1,
"max": null,
"min": null,
"show": false
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"cacheTimeout": null,
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [
{
"options": {
"0": {
"text": "NOK"
},
"1": {
"text": "OK"
}
},
"type": "value"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "#d44a3a",
"value": null
},
{
"color": "rgba(237, 129, 40, 0.89)",
"value": 1
},
{
"color": "#299c46",
"value": 1
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 5,
"w": 6,
"x": 0,
"y": 8
},
"id": 2,
"interval": null,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "8.0.6",
"repeat": "node",
"repeatDirection": "h",
"targets": [
{
"expr": "probe_success{instance=~\"$node\"}",
"format": "time_series",
"instant": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "",
"refId": "A"
}
],
"title": "$node",
"type": "stat"
}
],
"schemaVersion": 30,
"style": "dark",
"tags": [
"alerts",
"linux",
"windows"
],
"templating": {
"list": [
{
"allValue": null,
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"datasource": "Prometheus",
"definition": "",
"description": null,
"error": null,
"hide": 0,
"includeAll": true,
"label": "node",
"multi": true,
"name": "node",
"options": [],
"query": {
"query": "label_values(probe_success{job=\"ping\"}, instance) ",
"refId": "Prometheus-node-Variable-Query"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"tagValuesQuery": "",
"tagsQuery": "",
"type": "query",
"useTags": false
}
]
},
"time": {
"from": "now-24h",
"to": "now"
},
"timepicker": {
"refresh_intervals": [
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
"timezone": "",
"title": "Alerts - Server Status",
"uid": "pbHjqZzmk",
"version": 3
}

View File

@ -0,0 +1,903 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "Prometheus",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"description": "Fork of https://grafana.com/grafana/dashboards/5345 which uses 'instance' instead of 'target' label",
"editable": true,
"gnetId": 11175,
"graphTooltip": 0,
"id": 2,
"iteration": 1629329057681,
"links": [],
"panels": [
{
"collapsed": false,
"datasource": null,
"fieldConfig": {
"defaults": {},
"overrides": []
},
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 0
},
"id": 15,
"panels": [],
"repeat": "targets",
"title": "$targets UP/DOWN Status",
"type": "row"
},
{
"cacheTimeout": null,
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [
{
"options": {
"0": {
"text": "DOWN"
},
"1": {
"text": "UP"
}
},
"type": "value"
},
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "#d44a3a",
"value": null
},
{
"color": "rgba(237, 129, 40, 0.89)",
"value": 1
},
{
"color": "#299c46",
"value": 1
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 2,
"w": 24,
"x": 0,
"y": 1
},
"id": 2,
"interval": null,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "8.0.6",
"repeat": null,
"repeatDirection": "h",
"targets": [
{
"expr": "probe_success{instance=~\"$targets\"}",
"format": "time_series",
"interval": "$interval",
"intervalFactor": 1,
"refId": "A"
}
],
"title": "$targets",
"type": "stat"
},
{
"cacheTimeout": null,
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [
{
"options": {
"0": {
"text": "NO"
},
"1": {
"text": "YES"
}
},
"type": "value"
},
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "#d44a3a",
"value": null
},
{
"color": "rgba(237, 129, 40, 0.89)",
"value": 0
},
{
"color": "#299c46",
"value": 1
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 2,
"w": 6,
"x": 0,
"y": 3
},
"id": 18,
"interval": null,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "8.0.6",
"repeatDirection": "h",
"targets": [
{
"expr": "probe_http_ssl{instance=~\"$targets\"}",
"format": "time_series",
"interval": "$interval",
"intervalFactor": 1,
"refId": "A"
}
],
"title": "SSL",
"type": "stat"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "Prometheus",
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 6,
"w": 9,
"x": 6,
"y": 3
},
"hiddenSeries": false,
"id": 17,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"links": [],
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "8.0.6",
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "probe_duration_seconds{instance=~\"$targets\"}",
"format": "time_series",
"interval": "$interval",
"intervalFactor": 1,
"legendFormat": "seconds",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Probe Duration",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "s",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "Prometheus",
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 6,
"w": 9,
"x": 15,
"y": 3
},
"hiddenSeries": false,
"id": 21,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"links": [],
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "8.0.6",
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "probe_dns_lookup_time_seconds{instance=~\"$targets\"}",
"format": "time_series",
"interval": "$interval",
"intervalFactor": 1,
"legendFormat": "seconds",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "DNS Lookup",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "s",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"cacheTimeout": null,
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"decimals": 2,
"mappings": [
{
"options": {
"0": {
"text": "NO"
},
"1": {
"text": "YES"
}
},
"type": "value"
},
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "#d44a3a",
"value": null
},
{
"color": "rgba(237, 129, 40, 0.89)",
"value": 0
},
{
"color": "#299c46",
"value": 1209600
}
]
},
"unit": "dtdurations"
},
"overrides": []
},
"gridPos": {
"h": 2,
"w": 6,
"x": 0,
"y": 5
},
"id": 19,
"interval": null,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "8.0.6",
"repeatDirection": "h",
"targets": [
{
"expr": "probe_ssl_earliest_cert_expiry{instance=~\"$targets\"}-time()",
"format": "time_series",
"interval": "$interval",
"intervalFactor": 1,
"refId": "A"
}
],
"title": "SSL Cert Expiry",
"type": "stat"
},
{
"cacheTimeout": null,
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"decimals": 0,
"mappings": [
{
"options": {
"0": {
"text": "NO"
},
"1": {
"text": "YES"
}
},
"type": "value"
},
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "#299c46",
"value": null
},
{
"color": "rgba(237, 129, 40, 0.89)",
"value": 200
},
{
"color": "#d44a3a",
"value": 299
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 2,
"w": 6,
"x": 0,
"y": 7
},
"id": 20,
"interval": null,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "none",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "8.0.6",
"repeatDirection": "h",
"targets": [
{
"expr": "probe_http_status_code{instance=~\"$targets\"}",
"format": "time_series",
"interval": "$interval",
"intervalFactor": 1,
"refId": "A"
}
],
"title": "HTTP Status Code",
"type": "stat"
},
{
"cacheTimeout": null,
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "s"
},
"overrides": []
},
"gridPos": {
"h": 2,
"w": 12,
"x": 0,
"y": 9
},
"id": 23,
"interval": null,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "none",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "8.0.6",
"targets": [
{
"expr": "avg(probe_duration_seconds{instance=~\"$targets\"})",
"format": "time_series",
"interval": "$interval",
"intervalFactor": 1,
"refId": "A"
}
],
"title": "Average Probe Duration",
"type": "stat"
},
{
"cacheTimeout": null,
"datasource": "Prometheus",
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "s"
},
"overrides": []
},
"gridPos": {
"h": 2,
"w": 12,
"x": 12,
"y": 9
},
"id": 24,
"interval": null,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "none",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "8.0.6",
"targets": [
{
"expr": "avg(probe_dns_lookup_time_seconds{instance=~\"$targets\"})",
"format": "time_series",
"interval": "$interval",
"intervalFactor": 1,
"refId": "A"
}
],
"title": "Average DNS Lookup",
"type": "stat"
}
],
"refresh": "1m",
"schemaVersion": 30,
"style": "dark",
"tags": [
"blackbox",
"prometheus"
],
"templating": {
"list": [
{
"auto": true,
"auto_count": 10,
"auto_min": "10s",
"current": {
"selected": false,
"text": "auto",
"value": "$__auto_interval_interval"
},
"description": null,
"error": null,
"hide": 0,
"label": "Interval",
"name": "interval",
"options": [
{
"selected": true,
"text": "auto",
"value": "$__auto_interval_interval"
},
{
"selected": false,
"text": "5s",
"value": "5s"
},
{
"selected": false,
"text": "10s",
"value": "10s"
},
{
"selected": false,
"text": "30s",
"value": "30s"
},
{
"selected": false,
"text": "1m",
"value": "1m"
},
{
"selected": false,
"text": "10m",
"value": "10m"
},
{
"selected": false,
"text": "30m",
"value": "30m"
},
{
"selected": false,
"text": "1h",
"value": "1h"
},
{
"selected": false,
"text": "6h",
"value": "6h"
},
{
"selected": false,
"text": "12h",
"value": "12h"
},
{
"selected": false,
"text": "1d",
"value": "1d"
},
{
"selected": false,
"text": "7d",
"value": "7d"
},
{
"selected": false,
"text": "14d",
"value": "14d"
},
{
"selected": false,
"text": "30d",
"value": "30d"
}
],
"query": "5s,10s,30s,1m,10m,30m,1h,6h,12h,1d,7d,14d,30d",
"refresh": 2,
"skipUrlSync": false,
"type": "interval"
},
{
"allValue": null,
"current": {
"selected": false,
"text": "All",
"value": "$__all"
},
"datasource": "Prometheus",
"definition": "label_values(probe_success, instance)",
"description": null,
"error": null,
"hide": 0,
"includeAll": true,
"label": null,
"multi": true,
"name": "targets",
"options": [],
"query": {
"query": "label_values(probe_success, instance)",
"refId": "Prometheus-targets-Variable-Query"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"tagValuesQuery": "",
"tagsQuery": "",
"type": "query",
"useTags": false
}
]
},
"time": {
"from": "now-1h",
"to": "now"
},
"timepicker": {
"refresh_intervals": [
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
"timezone": "",
"title": "Blackbox Exporter Overview",
"uid": "xtkCtBkiz",
"version": 1
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
#!/bin/sh
if [ "$1" = "uninstall" ] ; then
echo ""
else # Installation procedure below
mkdir -p /data/monitoring/grafana /data/monitoring/data
chown 472:472 /data/monitoring/grafana -R
chown nobody:nogroup -R /data/monitoring/data
fi

View File

@ -0,0 +1,25 @@
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate $JC_CERT/fullchain.pem;
ssl_certificate_key $JC_CERT/privkey.pem;
server_name $JC_SERVICE www.$JC_SERVICE;
location / {
#allow 193.33.56.94/32;
#allow 2001:912:1480:130::0/64;
#deny all;
client_max_body_size 2G;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://$NET.101:3000/;
proxy_redirect off;
auth_basic "Entrez votre identifiant et mot de passe";
auth_basic_user_file $DATA_DIR/users.htpasswd;
}
}

View File

@ -0,0 +1,54 @@
# my global config
global:
scrape_interval: 1h
evaluation_interval: 1h
#scrape_timeout: 20s
# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets:
# - alertmanager:9093
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: "prometheus"
# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
static_configs:
- targets: ["localhost:9090"]
- job_name: 'blackbox'
metrics_path: /probe
params:
module: [http_2xx]
file_sd_configs:
- files: ['/etc/prometheus/blackbox-targets.yml']
relabel_configs:
- source_labels: [__address__] # SNI@IP form. first part is domain name
regex: "(.*)@.*"
target_label: __param_hostname
- source_labels: [__address__] # Take second Part for Target IP
regex: ".*@(.*)"
replacement: "https://${1}:443"
target_label: __param_target
- source_labels: [__address__] # Instance name is full line
target_label: instance
- source_labels: [] # Real blackbox ip
replacement: 172.29.50.102:9115
target_label: __address__
# For basic auth
#target_label: __param_headers

View File

@ -7,7 +7,7 @@ RADIO_HOST=mux.paj.oma-radio.fr
MUX_SERVER_PORT=9002
TELECOM_SERVER_PORT=3492
SOUNDBASE_DIR=/data/mux.paj.oma-radio.fr/soundbase
OMA_DOCKER_VERSION=dev
OMA_DOCKER_VERSION=recette
ICECAST=.110
SOUNDBASE_IP=10.99.99.7
SOUNDBASE_HOST=soundbase.paj.oma-radio.fr

View File

@ -1,6 +1,6 @@
#!/bin/bash
mkdir -p "$SOUNDBASE_DIR/pige"
chown 10000:10000 "$SOUNDBASE_DIR/pige" -R
chown 10000:10000 "$SOUNDBASE_DIR/pige"
cat "$SECRET_DIR/registry_pass" | docker login --username "$registry_user" --password-stdin registry.gitlab.com

View File

@ -1,6 +1,6 @@
version: '3'
services:
ambre_mux:
mux:
image: registry.gitlab.com/omaradio/core/oma-mux:$OMA_DOCKER_VERSION
env_file:
- .env
@ -8,6 +8,7 @@ services:
environment:
OMA_CONFIG_Client1Host: $NET$ICECAST
OMA_CONFIG_TelecommandeHost: $NET$TELECOM
OMA_CONFIG_Pige: on
OMA_CONFIG_LogLevel: 8
volumes:
- $SOUNDBASE_DIR/pige:/app/pige
@ -26,7 +27,7 @@ services:
memory: 100M
saphir_telecom_server:
telecomserver:
image: registry.gitlab.com/omaradio/core/oma-telecom-server:$OMA_DOCKER_VERSION
env_file: .env
ports:
@ -41,7 +42,7 @@ services:
cpus: '0.50'
memory: 100M
amarante_webserver:
webserver:
image: registry.gitlab.com/omaradio/core/oma-webserver:$OMA_DOCKER_VERSION
env_file: .env
environment:
@ -58,7 +59,7 @@ services:
deploy:
resources:
limits:
cpus: '0.50'
cpus: '0.5'
memory: 100M
transcode:
@ -80,26 +81,16 @@ services:
cpus: '0.50'
memory: 300M
#radioking:
# image: jeancloud/liquidsoap:1.3.7
# env_file: .env
# volumes:
# - ./radioking.liq:/radioking.liq
# command: /radioking.liq
# restart: unless-stopped
# networks:
# default:
# ipv4_address: $NET.111
icecast:
image: infiniteproject/icecast
image: jeancloud/icecast:$OMA_DOCKER_VERSION
restart: unless-stopped
environment:
# echo -n "source:pass" | base64
ICECAST_ADMIN_USERNAME: admin
ICECAST_ADMIN_EMAIL: contact@oma-radio.fr
ICECAST_LOCATION: Rhône-Alpes
ICECAST_SOURCE_TIMEOUT: 120
TZ: Europe/Paris
env_file: $DATA_DIR/.env
healthcheck:
@ -125,7 +116,6 @@ services:
- /tmp/uwsgi/$JC_SERVICE:/tmp/uwsgi
- /var/run/docker.sock:/var/run/docker.sock
- $SOUNDBASE_DIR:/soundbase
networks:
default:
ipv4_address: $NET.107
@ -135,7 +125,6 @@ services:
cpus: '0.50'
memory: 500M
networks:
default:
ipam:

View File

@ -76,27 +76,6 @@ server {
etag off;
}
location ~ /muxapi(/.*) {
auth_basic "Entrez votre identifiant et mot de passe";
auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd;
include uwsgi_params;
uwsgi_param PATH_INFO "$1";
uwsgi_param SCRIPT_NAME /muxapi;
uwsgi_pass unix:/tmp/uwsgi/$JC_SERVICE/uwsgi-api.sock;
client_max_body_size 0;
proxy_connect_timeout 6000;
proxy_send_timeout 60000;
proxy_read_timeout 6000;
send_timeout 6000;
# kill cache
add_header Last-Modified $date_gmt;
add_header Cache-Control 'private no-store, no-cache, must-revalidate, proxy- revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
}
location ~ /muxapi(/.*) {
auth_basic "Entrez votre identifiant et mot de passe";
auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd;
@ -116,4 +95,5 @@ server {
expires off;
etag off;
}
}

View File

@ -1,17 +0,0 @@
WEBSERVER=.105
MUX=.100
TELECOM=.101
SWEBSOCKET_PORT=2004
WEBSOCKET_PORT=2204
RADIO_HOST=mux.radiodemo.oma-radio.fr
MUX_SERVER_PORT=9004
TELECOM_SERVER_PORT=3494
SOUNDBASE_DIR=/data/mux.radiodemo.oma-radio.fr/
OMA_DOCKER_VERSION=dev
ICECAST=.110
SOUNDBASE_IP=10.99.99.7
SOUNDBASE_HOST=soundbase.radiodemo.oma-radio.fr
COMPOSE_NAME=muxradiodemooma-radiofr
DOCKER_INSTANCES_PREFIX=muxradiodemooma-radiofr-
DOCKER_INSTANCES_SUFIX=-1
OMA_CONFIG_LogLevel=8

View File

@ -1,4 +0,0 @@
#!/bin/bash
mkdir -p "$DATA_DIR/pige"
chown 10000:10000 "$DATA_DIR/pige" -R

View File

@ -1 +0,0 @@
liquidsoap-transcode.liq

View File

@ -1,44 +0,0 @@
#!/bin/bash
echo "Content-type: text/html"
echo ""
. .env
instance=''
since=''
until=''
action="$(echo "${REQUEST_URI##*/}" | tr -d '/\;!<>?#[]()"*.' | sed 's/&/\n/g')"
while IFS='=' read key value ; do
case "$key" in
instance)
instance="$value"
;;
since)
since="$value"
;;
until)
until="$value"
;;
list)
docker-compose ps -a --format json
;;
*)
exit 1
esac
done < <(echo "$action")
[ -z "$instance" ] && exit 2
[ -z "$since" ] && exit 3
[ -z "$until" ] && exit 4
pwd
echo docker-compose logs --since "$since" --until "$until" "$instance"
docker-compose logs --since "$since" --until "$until" "$instance" 2>&1
if [ "$?" -ne 0 ] ; then
echo failed
fi

View File

@ -43,6 +43,7 @@ server {
proxy_read_timeout 6000;
send_timeout 6000;
}
location /pige {
@ -81,7 +82,6 @@ server {
etag off;
}
location ~ /muxapi(/.*) {
auth_basic "Entrez votre identifiant et mot de passe";
auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd;

View File

@ -10,9 +10,10 @@ services:
ipv4_address: $NET.101
nextcloud:
image: nextcloud:28-fpm-alpine
image: nextcloud:30-fpm-alpine
volumes:
- $DATA_DIR/app:/var/www/html
- $DOCKER_DIR/zzz-fpm-additional-config.conf:/usr/local/etc/php-fpm.d/zzz-fpm-additional-config.conf
depends_on:
- db
restart: unless-stopped
@ -20,57 +21,57 @@ services:
default:
ipv4_address: $NET.100
etherpad:
image: etherpad/etherpad
environment:
- DB_TYPE=postgres
- DB_HOST=db_etherpad
- DB_PORT=5432
- DB_NAME=etherpad
- DB_USER=etherpad
- DB_PASS=toDEzbjoTLBCugi9MrDMtVEPCLwcDeUJ6ofvqEWqmNEm7YvjNBHnKVa
restart: unless-stopped
networks:
default:
ipv4_address: $NET.104
deploy:
resources:
limits:
cpus: '0.50'
memory: 1000M
db_etherpad:
image: postgres:11-alpine
restart: unless-stopped
volumes:
- $DATA_DIR/db_etherpad:/var/lib/postgresql/data
environment:
- POSTGRES_USER=etherpad
- POSTGRES_DB=etherpad
- POSTGRES_PASSWORD=toDEzbjoTLBCugi9MrDMtVEPCLwcDeUJ6ofvqEWqmNEm7YvjNBHnKVa
networks:
default:
ipv4_address: $NET.105
deploy:
resources:
limits:
cpus: '0.50'
memory: 1000M
ethercalc:
image: audreyt/ethercalc
environment:
REDIS_PORT_6379_TCP_ADDR: redis
REDIS_PORT_6379_TCP_PORT: 6379
restart: unless-stopped
networks:
default:
ipv4_address: $NET.102
deploy:
resources:
limits:
cpus: '0.50'
memory: 1000M
# etherpad:
# image: etherpad/etherpad
# environment:
# - DB_TYPE=postgres
# - DB_HOST=db_etherpad
# - DB_PORT=5432
# - DB_NAME=etherpad
# - DB_USER=etherpad
# - DB_PASS=toDEzbjoTLBCugi9MrDMtVEPCLwcDeUJ6ofvqEWqmNEm7YvjNBHnKVa
# restart: unless-stopped
# networks:
# default:
# ipv4_address: $NET.104
# deploy:
# resources:
# limits:
# cpus: '0.50'
# memory: 1000M
#
# db_etherpad:
# image: postgres:11-alpine
# restart: unless-stopped
# volumes:
# - $DATA_DIR/db_etherpad:/var/lib/postgresql/data
# environment:
# - POSTGRES_USER=etherpad
# - POSTGRES_DB=etherpad
# - POSTGRES_PASSWORD=toDEzbjoTLBCugi9MrDMtVEPCLwcDeUJ6ofvqEWqmNEm7YvjNBHnKVa
# networks:
# default:
# ipv4_address: $NET.105
# deploy:
# resources:
# limits:
# cpus: '0.50'
# memory: 1000M
#
# ethercalc:
# image: audreyt/ethercalc
# environment:
# REDIS_PORT_6379_TCP_ADDR: redis
# REDIS_PORT_6379_TCP_PORT: 6379
# restart: unless-stopped
# networks:
# default:
# ipv4_address: $NET.102
# deploy:
# resources:
# limits:
# cpus: '0.50'
# memory: 1000M
redis:
image: redis:latest
@ -100,8 +101,8 @@ services:
deploy:
resources:
limits:
cpus: '1'
memory: 2000M
cpus: '2'
memory: 4000M
networks:
default:

View File

@ -35,7 +35,7 @@ server {
# will add the domain to a hardcoded list that is shipped
# in all major browsers and getting removed from this list
# could take several months.
#add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always;
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always;
# set max upload size and increase upload timeout:
client_max_body_size 10G;
@ -275,6 +275,7 @@ server {
proxy_buffering off; # be careful, this line doesn't override any proxy_buffering on set in a conf.d/file.conf
proxy_set_header Host $host;
proxy_pass_header Server;
client_max_body_size 10G;
# Note you might want to pass these headers etc too.
#proxy_set_header X-Real-IP $remote_addr; # https://nginx.org/en/docs/http/ngx_http_proxy_module.html

View File

@ -0,0 +1,2 @@
[www]
pm.max_children = 10

View File

@ -0,0 +1,6 @@
GIT_SOURCE_REPO="https://gitlab.com/omaradio/website"
GIT_SOURCE_BRANCH=recette
RADIO_HOST=mux.paj.oma-radio.fr
USE_SSL=true
WEBSOCKET_PORT=2002
RADIO_NAME_PRETTY="Paj Radio"

View File

@ -0,0 +1,19 @@
#!/bin/bash
set -euo pipefail
# Si le site a déjà été build par le passé, curl termine lexécution du script en cas dabsence sur serveur corps.
[ -f "$HTTP_DIR/public/index.html" ] && { curl --head --fail-with-body $RADIO_HOST/fic/_series-_index.fic || exit 0 ; } >/dev/null
# Update git repo
git_update.sh -d "$HTTP_DIR" -o "-i $SECRET_DIR/gitlab-deploy.sshprivkey" -r "${GIT_SOURCE_BRANCH:-main}" "$GIT_SOURCE_REPO"
cd "$HTTP_DIR"
# Get remote content files
#rclone_ncloud_publiclink.sh
# Invalid cache
rm -rf "/tmp/hugo_cache_$USER"
# Build website
HUGO_CACHEDIR="/tmp/hugo_cache_$USER" hugo

View File

@ -0,0 +1,32 @@
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate $JC_CERT/fullchain.pem;
ssl_certificate_key $JC_CERT/privkey.pem;
server_name $JC_SERVICE www.$JC_SERVICE;
root $HTTP_DIR/public/;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
#add_header Content-Security-Policy "default-src 'none';frame-ancestors 'none'; script-src 'self' 'https://static.jean-cloud.net/player-interface/*' ; img-src 'self'; font-src 'self'; object-src 'none'; style-src 'self' 'https://static.jean-cloud.net/player-interface/*' 'https://cdn.jsdelivr.net/npm/*'; base-uri 'self'; form-action 'self';" always;
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options SAMEORIGIN always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header Permissions-Policy "geolocation='none';midi='none';notifications='none';push='none';microphone='none';camera='none';magnetometer='none';gyroscope='none';speaker='self';vibrate='none';fullscreen='self';payment='none';";
location / {
index index.html;
try_files $uri $uri/ =404;
}
location /manager {
return 301 $scheme://mux.$JC_SERVICE/manager;
}
location /buildscript/ {
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $DOCKER_DIR/server.sh;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
}
}

View File

@ -1,6 +1,15 @@
GIT_SOURCE_REPO="https://gitlab.com/omaradio/website"
GIT_SOURCE_BRANCH=dev
RADIO_HOST=mux.paj.oma-radio.fr
USE_SSL=true
WEBSOCKET_PORT=2002
RADIO_NAME_PRETTY="Paj Radio"
WEBSERVER=.105
MUX=.100
TELECOM=.101
SWEBSOCKET_PORT=2002
WEBSOCKET_PORT=2202
MUX_SERVER_PORT=9002
TELECOM_SERVER_PORT=3492
OMA_DOCKER_VERSION=recette
ICECAST=.110
SOUNDBASE_HOST=soundbase.paj.oma-radio.fr
COMPOSE_NAME=pajoma-radiofr
DOCKER_INSTANCES_PREFIX=pajoma-radiofr-
DOCKER_INSTANCES_SUFIX=-1
OMA_CONFIG_LogLevel=8

View File

@ -1,19 +1,16 @@
#!/bin/bash
set -euo pipefail
# Si le site a déjà été build par le passé, curl termine lexécution du script en cas dabsence sur serveur corps.
[ -f "$HTTP_DIR/public/index.html" ] && { curl --head --fail-with-body $RADIO_HOST/fic/_series-_index.fic || exit 0 ; } >/dev/null
# Update git repo
git_update.sh -d "$HTTP_DIR" -o "-i $SECRET_DIR/gitlab-deploy.sshprivkey" -r "${GIT_SOURCE_BRANCH:-main}" "$GIT_SOURCE_REPO"
cd "$HTTP_DIR"
# Get remote content files
#rclone_ncloud_publiclink.sh
# Invalid cache
rm -rf "/tmp/hugo_cache_$USER"
# Build website
HUGO_CACHEDIR="/tmp/hugo_cache_$USER" hugo
if [ ! -f "$DATA_DIR/.env" ] ; then
set +e
# head returns 141 on sigpipe
source_pass="$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 40)"
set -e
cat > "$DATA_DIR/.env" <<EOF
ICECAST_SOURCE_PASSWORD=$source_pass
ICECAST_ADMIN_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 40)
ICECAST_RELAY_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 40)
LIQUIDSOAP_SOURCE_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 40)
OMA_FORCE_Client1EnteteNext="Authorization: Basic $(echo -n "source:$source_pass" | base64)"
EOF
fi

View File

@ -1,16 +1,17 @@
version: '3'
services:
ambre_mux:
mux:
image: registry.gitlab.com/omaradio/core/oma-mux:$OMA_DOCKER_VERSION
env_file:
- .env
- $DATA_DIR/.env
environment:
OMA_CONFIG_Client1Host: $NET$ICECAST
OMA_CONFIG_TelecommandeHost: $NET$TELECOM
OMA_CONFIG_Pige: on
OMA_FORCE_Client1Host: $NET$ICECAST
OMA_FORCE_TelecommandeHost: $NET$TELECOM
OMA_FORCE_Pige: on
OMA_FORCE_LogLevel: 8
volumes:
- $SOUNDBASE_DIR/pige:/app/pige
- $DATA_DIR/soundbase/pige:/app/pige
ports:
- $MUX_SERVER_PORT:9000
depends_on:
@ -26,7 +27,7 @@ services:
memory: 100M
saphir_telecom_server:
telecomserver:
image: registry.gitlab.com/omaradio/core/oma-telecom-server:$OMA_DOCKER_VERSION
env_file: .env
ports:
@ -41,15 +42,15 @@ services:
cpus: '0.50'
memory: 100M
amarante_webserver:
webserver:
image: registry.gitlab.com/omaradio/core/oma-webserver:$OMA_DOCKER_VERSION
env_file: .env
environment:
OMA_CONFIG_TelecommandeHost: $NET$TELECOM
OMA_CONFIG_PigeTxtLoadFic: off
OMA_FORCE_TelecommandeHost: $NET$TELECOM
OMA_FORCE_PigeTxtLoadFic: off
restart: unless-stopped
volumes:
- $SOUNDBASE_DIR:/soundbase
- $DATA_DIR/soundbase:/soundbase
ports:
- $WEBSOCKET_PORT:9000
networks:
@ -68,7 +69,7 @@ services:
- $DATA_DIR/.env
volumes:
- ./liquidsoap.liq:/transcode.liq
- $SOUNDBASE_DIR:/soundbase
- $DATA_DIR/soundbase:/soundbase
command: /transcode.liq
restart: unless-stopped
networks:
@ -80,26 +81,16 @@ services:
cpus: '0.50'
memory: 300M
#radioking:
# image: jeancloud/liquidsoap:1.3.7
# env_file: .env
# volumes:
# - ./radioking.liq:/radioking.liq
# command: /radioking.liq
# restart: unless-stopped
# networks:
# default:
# ipv4_address: $NET.111
icecast:
image: infiniteproject/icecast
image: jeancloud/icecast:$OMA_DOCKER_VERSION
restart: unless-stopped
environment:
# echo -n "source:pass" | base64
ICECAST_ADMIN_USERNAME: admin
ICECAST_ADMIN_EMAIL: contact@oma-radio.fr
ICECAST_LOCATION: Rhône-Alpes
ICECAST_SOURCE_TIMEOUT: 120
TZ: Europe/Paris
env_file: $DATA_DIR/.env
healthcheck:
@ -124,7 +115,7 @@ services:
volumes:
- /tmp/uwsgi/$JC_SERVICE:/tmp/uwsgi
- /var/run/docker.sock:/var/run/docker.sock
- $SOUNDBASE_DIR:/soundbase
- $DATA_DIR/soundbase:/soundbase
networks:
default:
ipv4_address: $NET.107

View File

@ -1,32 +1,114 @@
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate $JC_CERT/fullchain.pem;
ssl_certificate_key $JC_CERT/privkey.pem;
server_name $JC_SERVICE www.$JC_SERVICE;
root $HTTP_DIR/public/;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
#add_header Content-Security-Policy "default-src 'none';frame-ancestors 'none'; script-src 'self' 'https://static.jean-cloud.net/player-interface/*' ; img-src 'self'; font-src 'self'; object-src 'none'; style-src 'self' 'https://static.jean-cloud.net/player-interface/*' 'https://cdn.jsdelivr.net/npm/*'; base-uri 'self'; form-action 'self';" always;
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options SAMEORIGIN always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header Permissions-Policy "geolocation='none';midi='none';notifications='none';push='none';microphone='none';camera='none';magnetometer='none';gyroscope='none';speaker='self';vibrate='none';fullscreen='self';payment='none';";
location / {
index index.html;
try_files $uri $uri/ =404;
}
location /manager {
return 301 $scheme://mux.$JC_SERVICE/manager;
}
location /buildscript/ {
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $DOCKER_DIR/server.sh;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server{
listen $SWEBSOCKET_PORT ssl;
ssl_certificate $JC_CERT/fullchain.pem;
ssl_certificate_key $JC_CERT/privkey.pem;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://$NET$WEBSERVER:9000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 120s;
}
}
# Ouverture du flux sur le port 80 pour le player de PAC
server {
listen 80;
server_name $JC_SERVICE mux.$JC_SERVICE;
location /direct.ogg {
client_max_body_size 0;
proxy_pass http://$NET$ICECAST:8000/direct.ogg;
# kill cache
add_header Last-Modified $date_gmt;
add_header Cache-Control 'private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name $JC_SERVICE mux.$JC_SERVICE;
ssl_certificate $JC_CERT/fullchain.pem;
ssl_certificate_key $JC_CERT/privkey.pem;
root "$DATA_DIR/soundbase/website";
location = /favicon.ico {
try_files /favicon.webp =404;
}
location / {
try_files $uri $uri/ =404;
}
location /soundbase {
alias "$DATA_DIR/soundbase";
try_files $uri $uri/ =404;
}
location ~ /muxapi(/.*) {
include uwsgi_params;
uwsgi_param PATH_INFO "$1";
uwsgi_param SCRIPT_NAME /api;
uwsgi_pass unix:/tmp/uwsgi/$JC_SERVICE/uwsgi-api.sock;
client_max_body_size 0;
proxy_connect_timeout 6000;
proxy_send_timeout 60000;
proxy_read_timeout 6000;
send_timeout 6000;
# kill cache
add_header Last-Modified $date_gmt;
add_header Cache-Control 'private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
add_header Access-Control-Allow-Origin https://soundbase.$JC_SERVICE;
if_modified_since off;
expires off;
etag off;
}
location /direct.ogg {
client_max_body_size 0;
proxy_pass http://$NET$ICECAST:8000/direct.ogg;
# kill cache
add_header Last-Modified $date_gmt;
add_header Cache-Control 'private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
}
location /direct.mp3 {
client_max_body_size 0;
proxy_pass http://$NET$ICECAST:8000/direct.mp3;
add_header Cache-Control 'private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
}
location /icecast/style.css {
client_max_body_size 0;
proxy_pass http://$NET$ICECAST:8000/style.css;
}
location /icecast/status.xsl {
client_max_body_size 0;
proxy_pass http://$NET$ICECAST:8000/status.xsl;
# kill cache
add_header Last-Modified $date_gmt;
add_header Cache-Control 'private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
}
location /manager {
return 301 https://$SOUNDBASE_HOST/manager;
}
}

1
services/privkey Normal file
View File

@ -0,0 +1 @@
IPetmqnsIKGr2r1/VppFxKeAdJoBeGSrrJWxnSsPJW0=

View File

@ -0,0 +1,96 @@
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name soundbase.radiodemo.oma-radio.fr;
ssl_certificate /data/dnscerts.jean-cloud.org/certs/live/soundbase.radiodemo.oma-radio.fr/fullchain.pem;
ssl_certificate_key /data/dnscerts.jean-cloud.org/certs/live/soundbase.radiodemo.oma-radio.fr/privkey.pem;
client_max_body_size 0;
proxy_connect_timeout 6000;
proxy_send_timeout 60000;
proxy_read_timeout 6000;
send_timeout 6000;
location / {
proxy_pass https://10.99.99.7;
proxy_set_header Host $host;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name soundbase.radiodev.oma-radio.fr;
ssl_certificate /data/dnscerts.jean-cloud.org/certs/live/soundbase.radiodev.oma-radio.fr/fullchain.pem;
ssl_certificate_key /data/dnscerts.jean-cloud.org/certs/live/soundbase.radiodev.oma-radio.fr/privkey.pem;
client_max_body_size 0;
proxy_connect_timeout 6000;
proxy_send_timeout 60000;
proxy_read_timeout 6000;
send_timeout 6000;
location / {
proxy_pass https://10.99.99.7;
proxy_set_header Host $host;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name soundbase.radiokipik.org;
ssl_certificate /data/dnscerts.jean-cloud.org/certs/live/soundbase.radiokipik.org/fullchain.pem;
ssl_certificate_key /data/dnscerts.jean-cloud.org/certs/live/soundbase.radiokipik.org/privkey.pem;
client_max_body_size 0;
proxy_connect_timeout 6000;
proxy_send_timeout 60000;
proxy_read_timeout 6000;
send_timeout 6000;
location / {
proxy_pass https://10.99.99.7;
proxy_set_header Host $host;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name monitoring.jean-cloud.net;
ssl_certificate /data/dnscerts.jean-cloud.org/certs/live/monitoring.jean-cloud.net/fullchain.pem;
ssl_certificate_key /data/dnscerts.jean-cloud.org/certs/live/monitoring.jean-cloud.net/privkey.pem;
client_max_body_size 0;
proxy_connect_timeout 6000;
proxy_send_timeout 60000;
proxy_read_timeout 6000;
send_timeout 6000;
location / {
proxy_pass https://10.99.99.7;
proxy_set_header Host $host;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name soundbase.paj.oma-radio.fr;
ssl_certificate /data/dnscerts.jean-cloud.org/certs/live/soundbase.paj.oma-radio.fr/fullchain.pem;
ssl_certificate_key /data/dnscerts.jean-cloud.org/certs/live/soundbase.paj.oma-radio.fr/privkey.pem;
client_max_body_size 0;
proxy_connect_timeout 6000;
proxy_send_timeout 60000;
proxy_read_timeout 6000;
send_timeout 6000;
location / {
proxy_pass https://10.99.99.7;
proxy_set_header Host $host;
}
}

View File

@ -0,0 +1,15 @@
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name soundbase.radiodemo.oma-radio.fr;
ssl_certificate /data/dnscerts.jean-cloud.org/certs/live/soundbase.radiodemo.oma-radio.fr/fullchain.pem;
ssl_certificate_key /data/dnscerts.jean-cloud.org/certs/live/soundbase.radiodemo.oma-radio.fr/privkey.pem;
location / {
proxy_pass http://10.99.99.7/;
proxy_set_header Host soundbase.radiodemo.oma-radio.fr;
}
}

View File

@ -2,7 +2,7 @@
set -euo pipefail
# Update git repo
git_update.sh -d "$HTTP_DIR" -b "${GIT_SOURCE_BRANCH:-main}" "$GIT_SOURCE_REPO"
git_update.sh -d "$HTTP_DIR" -r "${GIT_SOURCE_BRANCH:-main}" "$GIT_SOURCE_REPO"
cd "$HTTP_DIR"

View File

@ -9,7 +9,7 @@ TELECOM_SERVER_PORT=3494
OMA_DOCKER_VERSION=dev
ICECAST=.110
SOUNDBASE_HOST=soundbase.radiodemo.oma-radio.fr
COMPOSE_NAME=muxradiodemooma-radiofr
DOCKER_INSTANCES_PREFIX=muxradiodemooma-radiofr-
COMPOSE_NAME=radiodemooma-radiofr
DOCKER_INSTANCES_PREFIX=radiodemooma-radiofr-
DOCKER_INSTANCES_SUFIX=-1
OMA_CONFIG_LogLevel=8

View File

@ -2,9 +2,11 @@
set -euo pipefail
if [ ! -e "$DATA_DIR/.env" ] ; then
if [ ! -f "$DATA_DIR/.env" ] ; then
set +e
# head returns 141 on sigpipe
source_pass="$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 40)"
set -e
cat > "$DATA_DIR/.env" <<EOF
ICECAST_SOURCE_PASSWORD=$source_pass
ICECAST_ADMIN_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 40)

View File

@ -6,10 +6,10 @@ services:
- .env
- $DATA_DIR/.env
environment:
OMA_CONFIG_Client1Host: $NET$ICECAST
OMA_CONFIG_TelecommandeHost: $NET$TELECOM
OMA_CONFIG_Pige: on
OMA_CONFIG_LogLevel: 8
OMA_FORCE_Client1Host: $NET$ICECAST
OMA_FORCE_TelecommandeHost: $NET$TELECOM
OMA_FORCE_Pige: on
OMA_FORCE_LogLevel: 8
volumes:
- $DATA_DIR/soundbase/pige:/app/pige
ports:
@ -46,8 +46,8 @@ services:
image: registry.gitlab.com/omaradio/core/oma-webserver:$OMA_DOCKER_VERSION
env_file: .env
environment:
OMA_CONFIG_TelecommandeHost: $NET$TELECOM
OMA_CONFIG_PigeTxtLoadFic: off
OMA_FORCE_TelecommandeHost: $NET$TELECOM
OMA_FORCE_PigeTxtLoadFic: off
restart: unless-stopped
volumes:
- $DATA_DIR/soundbase:/soundbase

View File

@ -0,0 +1,80 @@
#!/usr/bin/liquidsoap
# Extract timestamp from pige path
def ts_from_filepath (filepath)
splitpath = string.split(separator='/', filepath)
# Keep only filename
filename = list.nth(splitpath,list.length(splitpath)-1)
int_of_string(list.hd(string.split(separator='\\.', filename)))
end
# Remove pige from now-1month
def clean_single_old_pige(ts)
# ts of one month sooner
ts = ts - 2678400
filepath = "/soundbase/pige/#{ts}.ogg"
if file.exists("#{filepath}") then
process.run("rm #{filepath}")
end
end
# Remove a pige file if it is too old
def clean_if_old(filename)
filepath = "/soundbase/pige/#{filename}"
if ( ts_from_filepath (filename) < int_of_float(time()) - 2678400 ) then
process.run("rm #{filepath}")
end
end
# Check that the timestamp starts exactly on a minute
def integrity_check(ts)
if ts mod 60 != 0 then
log.important("#{ts} is to fix")
end
end
# Routine integrity check for each files
def clean_and_check (filepath)
ts = ts_from_filepath (filepath)
integrity_check (ts)
clean_single_old_pige (ts)
end
# Exaustive integrity check
def clean_and_check_all ()
list.iter(clean_if_old, file.ls("/soundbase/pige/"))
list.iter(clean_and_check, file.ls("/soundbase/pige/"))
end
# Mux
#input1 = mksafe(input.harbor("direct.ogg",port=8000,password=getenv("ICECAST_SOURCE_PASSWORD")))
input1 = mksafe(input.http("http://icecast:8000/direct.ogg"))
# Direct mp3
output.icecast(
%mp3(bitrate=128, samplerate=22050, stereo=false),
mount="/direct.mp3",
host="icecast", port=8000, password=getenv("ICECAST_SOURCE_PASSWORD"),
input1)
# Radioking
#output.icecast(
# %mp3(bitrate=128, samplerate=22050, stereo=false),
# mount="/test355",
# host="live.radioking.com", port=80, user="", password="",
# input)
# Direct ogg
#output.icecast(
# %vorbis(samplerate=44100, channels=1, quality=0.2),
# mount="/direct.ogg",
# host="icecast", port=8000, password=getenv("ICECAST_SOURCE_PASSWORD"),
# input1)
# Pige
output.file(%vorbis(samplerate=44100, channels=1, quality=0.2), {"/soundbase/pige/#{int_of_float(time())}.ogg"}, input1, reopen_when={0s}, reopen_delay=1.0, on_close=clean_and_check)
# Integrity checks
clean_and_check_all()

View File

@ -19,6 +19,22 @@ server{
}
}
# Ouverture du flux sur le port 80 pour le player de PAC
server {
listen 80;
server_name $JC_SERVICE mux.$JC_SERVICE;
location /direct.ogg {
client_max_body_size 0;
proxy_pass http://$NET$ICECAST:8000/direct.ogg;
# kill cache
add_header Last-Modified $date_gmt;
add_header Cache-Control 'private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
@ -26,16 +42,41 @@ server {
ssl_certificate $JC_CERT/fullchain.pem;
ssl_certificate_key $JC_CERT/privkey.pem;
location /soundbase {
alias "$DATA_DIR/soundbase";
try_files $uri $uri/ =404;
root "$DATA_DIR/soundbase/website";
location = /favicon.ico {
try_files /favicon.webp =404;
}
location / {
root "$DATA_DIR/soundbase/website";
try_files $uri $uri/ =404;
}
location /soundbase {
alias "$DATA_DIR/soundbase";
try_files $uri $uri/ =404;
}
location ~ /muxapi(/.*) {
include uwsgi_params;
uwsgi_param PATH_INFO "$1";
uwsgi_param SCRIPT_NAME /api;
uwsgi_pass unix:/tmp/uwsgi/$JC_SERVICE/uwsgi-api.sock;
client_max_body_size 0;
proxy_connect_timeout 6000;
proxy_send_timeout 60000;
proxy_read_timeout 6000;
send_timeout 6000;
# kill cache
add_header Last-Modified $date_gmt;
add_header Cache-Control 'private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
add_header Access-Control-Allow-Origin https://soundbase.$JC_SERVICE;
if_modified_since off;
expires off;
etag off;
}
location /direct.ogg {
client_max_body_size 0;
@ -66,4 +107,11 @@ server {
expires off;
etag off;
}
<<<<<<< HEAD
=======
location /manager {
return 301 https://$SOUNDBASE_HOST/manager;
}
>>>>>>> 9f3b59b (next step)
}

View File

@ -0,0 +1,16 @@
WEBSOCKET_PORT=2006
WEBSERVER=.105
MUX=.100
TELECOM=.101
SWEBSOCKET_PORT=2006
WEBSOCKET_PORT=2206
MUX_SERVER_PORT=9006
TELECOM_SERVER_PORT=3496
OMA_DOCKER_VERSION=dev
ICECAST=.110
HEAD_HOST=radiodev.oma-radio.fr
SOUNDBASE_HOST=soundbase.radiodev.oma-radio.fr
COMPOSE_NAME=radiodevoma-radiofr
DOCKER_INSTANCES_PREFIX=radiodevoma-radiofr-
DOCKER_INSTANCES_SUFIX=-1
OMA_CONFIG_LogLevel=8

View File

@ -1,12 +1,16 @@
#!/bin/bash
if [ ! -e "$DATA_DIR/.env" ] ; then
if [ ! -f "$DATA_DIR/.env" ] ; then
set +e
# head returns 141 on sigpipe
source_pass="$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 40)"
set -e
cat > "$DATA_DIR/.env" <<EOF
ICECAST_SOURCE_PASSWORD=$source_pass
ICECAST_ADMIN_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 40)
ICECAST_RELAY_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 40)
LIQUIDSOAP_SOURCE_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 40)
OMA_CONFIG_Client1EnteteNext="Authorization: Basic $(echo "source:$source_pass" | base64)"
OMA_FORCE_Client1EnteteNext="Authorization: Basic $(echo -n "source:$source_pass" | base64)"
EOF
fi

View File

@ -0,0 +1,135 @@
version: '3'
services:
mux:
image: registry.gitlab.com/omaradio/core/oma-mux:$OMA_DOCKER_VERSION
env_file:
- .env
- $DATA_DIR/.env
environment:
OMA_FORCE_Client1Host: $NET$ICECAST
OMA_FORCE_TelecommandeHost: $NET$TELECOM
OMA_FORCE_Pige: on
OMA_FORCE_LogLevel: 8
volumes:
- $DATA_DIR/soundbase/pige:/app/pige
ports:
- $MUX_SERVER_PORT:9000
depends_on:
- transcode
restart: unless-stopped
networks:
default:
ipv4_address: $NET$MUX
deploy:
resources:
limits:
cpus: '0.50'
memory: 100M
telecomserver:
image: registry.gitlab.com/omaradio/core/oma-telecom-server:$OMA_DOCKER_VERSION
env_file: .env
ports:
- $TELECOM_SERVER_PORT:3490
restart: unless-stopped
networks:
default:
ipv4_address: $NET$TELECOM
deploy:
resources:
limits:
cpus: '0.50'
memory: 100M
webserver:
image: registry.gitlab.com/omaradio/core/oma-webserver:$OMA_DOCKER_VERSION
env_file: .env
environment:
OMA_FORCE_TelecommandeHost: $NET$TELECOM
OMA_FORCE_PigeTxtLoadFic: off
restart: unless-stopped
volumes:
- $DATA_DIR/soundbase:/soundbase
ports:
- $WEBSOCKET_PORT:9000
networks:
default:
ipv4_address: $NET$WEBSERVER
deploy:
resources:
limits:
cpus: '0.5'
memory: 100M
transcode:
image: savonet/liquidsoap:v2.1.4
env_file:
- .env
- $DATA_DIR/.env
volumes:
- ./liquidsoap.liq:/transcode.liq
- $DATA_DIR/soundbase:/soundbase
command: /transcode.liq
restart: unless-stopped
networks:
default:
ipv4_address: $NET.108
deploy:
resources:
limits:
cpus: '0.50'
memory: 500M
icecast:
image: jeancloud/icecast:$OMA_DOCKER_VERSION
restart: unless-stopped
environment:
# echo -n "source:pass" | base64
ICECAST_ADMIN_USERNAME: admin
ICECAST_ADMIN_EMAIL: contact@oma-radio.fr
ICECAST_LOCATION: Rhône-Alpes
ICECAST_SOURCE_TIMEOUT: 120
ICECAST_HOSTNAME: $HEAD_HOST
# LOG: 4 -> Debug
ICECAST_LOGLEVEL: 4
TZ: Europe/Paris
env_file: $DATA_DIR/.env
healthcheck:
test: "wget http://127.0.0.1:8000/direct.ogg -O - -t 1 -T 3 -S --spider 2>&1 | grep '200 OK' && wget http://127.0.0.1:8000/direct.mp3 -O - -t 1 -T 3 -S --spider 2>&1 | grep '200 OK'"
interval: 1h0m0s
timeout: 10s
retries: 3
start_period: 1m0s
networks:
default:
ipv4_address: $NET$ICECAST
system_api:
image: jeancloud/system-api:$OMA_DOCKER_VERSION
env_file: .env
environment:
UID: 33
SOUNDBASE_PATH: /soundbase
MOUNT: /muxapi
CONFIG_PATH: /config
restart: unless-stopped
volumes:
- /tmp/uwsgi/$JC_SERVICE:/tmp/uwsgi
- /var/run/docker.sock:/var/run/docker.sock
- $DATA_DIR/soundbase:/soundbase
networks:
default:
ipv4_address: $NET.107
deploy:
resources:
limits:
cpus: '0.50'
memory: 500M
networks:
default:
ipam:
config:
- subnet: $NET.0/24

Some files were not shown because too many files have changed in this diff Show More