diff --git a/installing/debootstrap_ordis_portables.sh b/installing/debootstrap_ordis_portables.sh index 787acae..64eda36 100755 --- a/installing/debootstrap_ordis_portables.sh +++ b/installing/debootstrap_ordis_portables.sh @@ -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'" diff --git a/services/builder.rimarima.fr/.env b/old_services/builder.rimarima.fr/.env similarity index 100% rename from services/builder.rimarima.fr/.env rename to old_services/builder.rimarima.fr/.env diff --git a/services/builder.rimarima.fr/deploy.sh b/old_services/builder.rimarima.fr/deploy.sh similarity index 100% rename from services/builder.rimarima.fr/deploy.sh rename to old_services/builder.rimarima.fr/deploy.sh diff --git a/services/builder.rimarima.fr/deploy_user.sh b/old_services/builder.rimarima.fr/deploy_user.sh similarity index 100% rename from services/builder.rimarima.fr/deploy_user.sh rename to old_services/builder.rimarima.fr/deploy_user.sh diff --git a/services/builder.rimarima.fr/hugobuilder.dockerfile b/old_services/builder.rimarima.fr/hugobuilder.dockerfile similarity index 100% rename from services/builder.rimarima.fr/hugobuilder.dockerfile rename to old_services/builder.rimarima.fr/hugobuilder.dockerfile diff --git a/services/builder.rimarima.fr/index.html b/old_services/builder.rimarima.fr/index.html similarity index 100% rename from services/builder.rimarima.fr/index.html rename to old_services/builder.rimarima.fr/index.html diff --git a/services/builder.rimarima.fr/nginx_server.conf b/old_services/builder.rimarima.fr/nginx_server.conf similarity index 100% rename from services/builder.rimarima.fr/nginx_server.conf rename to old_services/builder.rimarima.fr/nginx_server.conf diff --git a/services/builder.rimarima.fr/server.sh b/old_services/builder.rimarima.fr/server.sh similarity index 100% rename from services/builder.rimarima.fr/server.sh rename to old_services/builder.rimarima.fr/server.sh diff --git a/services/compagnienouvelle.fr/.env b/old_services/compagnienouvelle.fr/.env similarity index 100% rename from services/compagnienouvelle.fr/.env rename to old_services/compagnienouvelle.fr/.env diff --git a/services/compagnienouvelle.fr/deploy.sh b/old_services/compagnienouvelle.fr/deploy.sh similarity index 100% rename from services/compagnienouvelle.fr/deploy.sh rename to old_services/compagnienouvelle.fr/deploy.sh diff --git a/services/compagnienouvelle.fr/deploy_user.sh b/old_services/compagnienouvelle.fr/deploy_user.sh similarity index 100% rename from services/compagnienouvelle.fr/deploy_user.sh rename to old_services/compagnienouvelle.fr/deploy_user.sh diff --git a/services/compagnienouvelle.fr/nginx_server.conf b/old_services/compagnienouvelle.fr/nginx_server.conf similarity index 100% rename from services/compagnienouvelle.fr/nginx_server.conf rename to old_services/compagnienouvelle.fr/nginx_server.conf diff --git a/services/rimarima.fr/.env b/old_services/rimarima.fr/.env similarity index 100% rename from services/rimarima.fr/.env rename to old_services/rimarima.fr/.env diff --git a/services/rimarima.fr/LINKS. DO NOT EDIT b/old_services/rimarima.fr/LINKS. DO NOT EDIT similarity index 100% rename from services/rimarima.fr/LINKS. DO NOT EDIT rename to old_services/rimarima.fr/LINKS. DO NOT EDIT diff --git a/services/rimarima.fr/deploy.sh b/old_services/rimarima.fr/deploy.sh similarity index 100% rename from services/rimarima.fr/deploy.sh rename to old_services/rimarima.fr/deploy.sh diff --git a/services/rimarima.fr/deploy_user.sh b/old_services/rimarima.fr/deploy_user.sh similarity index 100% rename from services/rimarima.fr/deploy_user.sh rename to old_services/rimarima.fr/deploy_user.sh diff --git a/services/rimarima.fr/nginx_server.conf b/old_services/rimarima.fr/nginx_server.conf similarity index 100% rename from services/rimarima.fr/nginx_server.conf rename to old_services/rimarima.fr/nginx_server.conf diff --git a/provisioning/inventory.ini b/provisioning/inventory.ini index 46201fe..52b7845 100644 --- a/provisioning/inventory.ini +++ b/provisioning/inventory.ini @@ -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 diff --git a/provisioning/playbook.yml b/provisioning/playbook.yml index a62d3bf..538a795 100755 --- a/provisioning/playbook.yml +++ b/provisioning/playbook.yml @@ -110,3 +110,5 @@ ##- deploy_all +# TODO +# journalctl --vacuum-size=500M diff --git a/provisioning/roles/deploy_all/files/bin/deploy_as.c b/provisioning/roles/deploy_all/files/bin/deploy_as.c index 1e4f560..173647d 100644 --- a/provisioning/roles/deploy_all/files/bin/deploy_as.c +++ b/provisioning/roles/deploy_all/files/bin/deploy_as.c @@ -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 \n",argv[0]); + if ( argc != 2 && argc != 3) { + printf("usage: %s [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; } diff --git a/provisioning/roles/deploy_all/files/bin/deploy_service.sh b/provisioning/roles/deploy_all/files/bin/deploy_service.sh index c24adbe..6d4cb21 100755 --- a/provisioning/roles/deploy_all/files/bin/deploy_service.sh +++ b/provisioning/roles/deploy_all/files/bin/deploy_service.sh @@ -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 diff --git a/provisioning/roles/deploy_all/files/bin/deploy_user.sh b/provisioning/roles/deploy_all/files/bin/deploy_user.sh index 496bd3d..836c428 100755 --- a/provisioning/roles/deploy_all/files/bin/deploy_user.sh +++ b/provisioning/roles/deploy_all/files/bin/deploy_user.sh @@ -1,14 +1,24 @@ #!/bin/bash set -euo pipefail -if [ "$#" -ne 1 ] || [ -z "$1" ] ; then - echo "Usage: $0 " +if [ "$#" -lt 1 ] || [ "$#" -gt 2 ] || [ -z "$1" ] ; then + echo "Usage: $0 [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" diff --git a/provisioning/roles/deploy_all/files/bin/deployall.sh b/provisioning/roles/deploy_all/files/bin/deployall.sh index c286d17..775052b 100755 --- a/provisioning/roles/deploy_all/files/bin/deployall.sh +++ b/provisioning/roles/deploy_all/files/bin/deployall.sh @@ -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" diff --git a/provisioning/roles/deploy_all/files/bin/findcert.sh b/provisioning/roles/deploy_all/files/bin/findcert.sh index 9d415f1..a742745 100755 --- a/provisioning/roles/deploy_all/files/bin/findcert.sh +++ b/provisioning/roles/deploy_all/files/bin/findcert.sh @@ -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 diff --git a/provisioning/roles/deploy_all/files/bin/gen_env.sh b/provisioning/roles/deploy_all/files/bin/gen_env.sh index 4135bf1..640220f 100755 --- a/provisioning/roles/deploy_all/files/bin/gen_env.sh +++ b/provisioning/roles/deploy_all/files/bin/gen_env.sh @@ -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" diff --git a/provisioning/roles/deploy_all/files/bin/git_update.sh b/provisioning/roles/deploy_all/files/bin/git_update.sh index 51d7206..c5db0b7 100755 --- a/provisioning/roles/deploy_all/files/bin/git_update.sh +++ b/provisioning/roles/deploy_all/files/bin/git_update.sh @@ -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 diff --git a/provisioning/roles/deploy_all/files/bin/rclone_ncloud_publiclink.sh b/provisioning/roles/deploy_all/files/bin/rclone_ncloud_publiclink.sh index 78d41d9..b01e81c 100755 --- a/provisioning/roles/deploy_all/files/bin/rclone_ncloud_publiclink.sh +++ b/provisioning/roles/deploy_all/files/bin/rclone_ncloud_publiclink.sh @@ -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 diff --git a/provisioning/roles/deploy_all/files/bin/resolvable.sh b/provisioning/roles/deploy_all/files/bin/resolvable.sh index f8086bf..495c631 100755 --- a/provisioning/roles/deploy_all/files/bin/resolvable.sh +++ b/provisioning/roles/deploy_all/files/bin/resolvable.sh @@ -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 diff --git a/provisioning/roles/deploy_all/files/secrets.volume b/provisioning/roles/deploy_all/files/secrets.volume index d2f5a16..92721ec 100644 Binary files a/provisioning/roles/deploy_all/files/secrets.volume and b/provisioning/roles/deploy_all/files/secrets.volume differ diff --git a/provisioning/roles/deploy_all/tasks/main.yml b/provisioning/roles/deploy_all/tasks/main.yml index 2179a07..0047ae2 100644 --- a/provisioning/roles/deploy_all/tasks/main.yml +++ b/provisioning/roles/deploy_all/tasks/main.yml @@ -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/" diff --git a/services/archive1max.jean-cloud.net/.env b/services/archive1max.jean-cloud.net/.env new file mode 100644 index 0000000..c175e9d --- /dev/null +++ b/services/archive1max.jean-cloud.net/.env @@ -0,0 +1,2 @@ +DATA_DIR=/tmp/mock_data +NET=172.29.1 diff --git a/services/archive1max.jean-cloud.net/docker-compose.yml b/services/archive1max.jean-cloud.net/docker-compose.yml new file mode 100755 index 0000000..49cec3c --- /dev/null +++ b/services/archive1max.jean-cloud.net/docker-compose.yml @@ -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 diff --git a/services/archive1max.jean-cloud.net/maintenance.sh b/services/archive1max.jean-cloud.net/maintenance.sh new file mode 100644 index 0000000..b496f1e --- /dev/null +++ b/services/archive1max.jean-cloud.net/maintenance.sh @@ -0,0 +1 @@ +docker-compose exec -u www-data nextcloud php occ maintenance:mode --on diff --git a/services/archive1max.jean-cloud.net/nginx_server.conf b/services/archive1max.jean-cloud.net/nginx_server.conf new file mode 100755 index 0000000..ac35877 --- /dev/null +++ b/services/archive1max.jean-cloud.net/nginx_server.conf @@ -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; + diff --git a/services/benevoles32.karnaval.fr/docker-compose.yml b/services/benevoles32.karnaval.fr/docker-compose.yml index b0ba192..b52071d 100755 --- a/services/benevoles32.karnaval.fr/docker-compose.yml +++ b/services/benevoles32.karnaval.fr/docker-compose.yml @@ -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 diff --git a/services/benevoles32.karnaval.fr/nginx_server.conf b/services/benevoles32.karnaval.fr/nginx_server.conf index 2d01715..4f751b6 100755 --- a/services/benevoles32.karnaval.fr/nginx_server.conf +++ b/services/benevoles32.karnaval.fr/nginx_server.conf @@ -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; diff --git a/services/benevoles33.karnaval.fr/.env b/services/benevoles33.karnaval.fr/.env new file mode 100644 index 0000000..e69de29 diff --git a/services/benevoles33.karnaval.fr/docker-compose.yml b/services/benevoles33.karnaval.fr/docker-compose.yml new file mode 100755 index 0000000..c4ddcff --- /dev/null +++ b/services/benevoles33.karnaval.fr/docker-compose.yml @@ -0,0 +1,47 @@ +version: '3' +services: + app: + # Ce nom d’image 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 diff --git a/services/benevoles33.karnaval.fr/nginx_server.conf b/services/benevoles33.karnaval.fr/nginx_server.conf new file mode 100755 index 0000000..2d01715 --- /dev/null +++ b/services/benevoles33.karnaval.fr/nginx_server.conf @@ -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; + } + + +} diff --git a/services/collectif-karafon.fr/deploy_user.sh b/services/collectif-karafon.fr/deploy_user.sh index 1dcddee..39b9728 100755 --- a/services/collectif-karafon.fr/deploy_user.sh +++ b/services/collectif-karafon.fr/deploy_user.sh @@ -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" diff --git a/services/core.oma-radio.fr/deploy_user.sh b/services/core.oma-radio.fr/deploy_user.sh new file mode 100755 index 0000000..8b1d0fd --- /dev/null +++ b/services/core.oma-radio.fr/deploy_user.sh @@ -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." diff --git a/services/default_server/nginx_server.conf b/services/default_server/nginx_server.conf new file mode 100644 index 0000000..65fca0a --- /dev/null +++ b/services/default_server/nginx_server.conf @@ -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 '

Erreur du service

Ce service n’est pas accessible actuellement. Si cela n’est pas normal prévenez-nous à cette adresse : contact@jean-cloud.net

Merci ! :)

'; + } +} diff --git a/services/dnscerts.jean-cloud.org/.env b/services/dnscerts.jean-cloud.org/.env new file mode 100644 index 0000000..b61ba96 --- /dev/null +++ b/services/dnscerts.jean-cloud.org/.env @@ -0,0 +1 @@ +SERVERS="izzo.jean-cloud.org raku.jean-cloud.org montbonnot.jean-cloud.org" diff --git a/services/dnscerts.jean-cloud.org/acme-dns.sh b/services/dnscerts.jean-cloud.org/acme-dns.sh index be40e37..8cd9eaa 100755 --- a/services/dnscerts.jean-cloud.org/acme-dns.sh +++ b/services/dnscerts.jean-cloud.org/acme-dns.sh @@ -1,18 +1,45 @@ #!/bin/bash -if [ "$#" -ne 2 ] ; then - echo "Usage: $0 " >&2 +if [ "$#" -ne 4 ] ; then + echo "Usage: $0 " >&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 diff --git a/services/dnscerts.jean-cloud.org/deploy_user.sh b/services/dnscerts.jean-cloud.org/deploy_user.sh index 3041b06..1413679 100755 --- a/services/dnscerts.jean-cloud.org/deploy_user.sh +++ b/services/dnscerts.jean-cloud.org/deploy_user.sh @@ -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 diff --git a/services/ffcoinche.fr/.env b/services/ffcoinche.fr/.env new file mode 100644 index 0000000..d9d1fef --- /dev/null +++ b/services/ffcoinche.fr/.env @@ -0,0 +1,2 @@ +GIT_SOURCE_REPO="https://framagit.org/adrian-amaglio/ffcoinche.fr" + diff --git a/services/ffcoinche.fr/deploy_user.sh b/services/ffcoinche.fr/deploy_user.sh new file mode 100755 index 0000000..c67f5b4 --- /dev/null +++ b/services/ffcoinche.fr/deploy_user.sh @@ -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" diff --git a/services/ffcoinche.fr/nginx_server.conf b/services/ffcoinche.fr/nginx_server.conf new file mode 100755 index 0000000..4558a3d --- /dev/null +++ b/services/ffcoinche.fr/nginx_server.conf @@ -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; + } +} diff --git a/services/kipik.studios.oma-radio.fr/deploy.sh b/services/kipik.studios.oma-radio.fr/deploy.sh new file mode 100755 index 0000000..a296479 --- /dev/null +++ b/services/kipik.studios.oma-radio.fr/deploy.sh @@ -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" diff --git a/services/kipik.studios.oma-radio.fr/wgns-kipik.sh b/services/kipik.studios.oma-radio.fr/wgns-kipik.sh new file mode 100755 index 0000000..de1a9c6 --- /dev/null +++ b/services/kipik.studios.oma-radio.fr/wgns-kipik.sh @@ -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 +" diff --git a/services/letourbillon-podcast.fr/.env b/services/letourbillon-podcast.fr/.env new file mode 100644 index 0000000..5b54b4e --- /dev/null +++ b/services/letourbillon-podcast.fr/.env @@ -0,0 +1 @@ +SFTP_USER=letourbillonRO diff --git a/services/letourbillon-podcast.fr/LINKS. DO NOT EDIT b/services/letourbillon-podcast.fr/LINKS. DO NOT EDIT new file mode 100644 index 0000000..e69de29 diff --git a/services/letourbillon-podcast.fr/deploy.sh b/services/letourbillon-podcast.fr/deploy.sh new file mode 120000 index 0000000..e857506 --- /dev/null +++ b/services/letourbillon-podcast.fr/deploy.sh @@ -0,0 +1 @@ +../sftp_jc/deploy.sh \ No newline at end of file diff --git a/services/letourbillon-podcast.fr/deploy_user.sh b/services/letourbillon-podcast.fr/deploy_user.sh new file mode 120000 index 0000000..3d4ee19 --- /dev/null +++ b/services/letourbillon-podcast.fr/deploy_user.sh @@ -0,0 +1 @@ +../sftp_jc/deploy_user.sh \ No newline at end of file diff --git a/services/letourbillon-podcast.fr/nginx_server.conf b/services/letourbillon-podcast.fr/nginx_server.conf new file mode 120000 index 0000000..c63a303 --- /dev/null +++ b/services/letourbillon-podcast.fr/nginx_server.conf @@ -0,0 +1 @@ +../sftp_jc/nginx_server.conf \ No newline at end of file diff --git a/services/monitoring.jean-cloud.net/create_monitoring_list.sh b/services/monitoring.jean-cloud.net/create_monitoring_list.sh new file mode 100755 index 0000000..ffdff87 --- /dev/null +++ b/services/monitoring.jean-cloud.net/create_monitoring_list.sh @@ -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" diff --git a/services/monitoring.jean-cloud.net/docker-compose.yml b/services/monitoring.jean-cloud.net/docker-compose.yml new file mode 100644 index 0000000..84e4191 --- /dev/null +++ b/services/monitoring.jean-cloud.net/docker-compose.yml @@ -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 diff --git a/services/monitoring.jean-cloud.net/grafana.ini b/services/monitoring.jean-cloud.net/grafana.ini new file mode 100644 index 0000000..b427e33 --- /dev/null +++ b/services/monitoring.jean-cloud.net/grafana.ini @@ -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 + diff --git a/services/monitoring.jean-cloud.net/grafana_dashboards/alerts_server_status.json b/services/monitoring.jean-cloud.net/grafana_dashboards/alerts_server_status.json new file mode 100644 index 0000000..a4e400f --- /dev/null +++ b/services/monitoring.jean-cloud.net/grafana_dashboards/alerts_server_status.json @@ -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 +} diff --git a/services/monitoring.jean-cloud.net/grafana_dashboards/blackbox_overview.json b/services/monitoring.jean-cloud.net/grafana_dashboards/blackbox_overview.json new file mode 100644 index 0000000..11850a6 --- /dev/null +++ b/services/monitoring.jean-cloud.net/grafana_dashboards/blackbox_overview.json @@ -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 +} diff --git a/services/monitoring.jean-cloud.net/grafana_dashboards/cadvisor_node_exporter.json b/services/monitoring.jean-cloud.net/grafana_dashboards/cadvisor_node_exporter.json new file mode 100644 index 0000000..f1ec617 --- /dev/null +++ b/services/monitoring.jean-cloud.net/grafana_dashboards/cadvisor_node_exporter.json @@ -0,0 +1,2490 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Dashboard with details of the container metrics and host OS metrics.", + "editable": true, + "gnetId": 10566, + "graphTooltip": 1, + "id": 6, + "iteration": 1629329112111, + "links": [], + "panels": [ + { + "cacheTimeout": null, + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "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": 4, + "w": 4, + "x": 0, + "y": 0 + }, + "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": "time() - node_boot_time_seconds{instance=~\"$node\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 1800 + } + ], + "title": "Uptime", + "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": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 4, + "y": 0 + }, + "id": 31, + "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": "count(rate(container_last_seen{id=~\"/docker/.*\",instance=~\"$node\"}[5m]))", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "refId": "A", + "step": 1800 + } + ], + "title": "Containers", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 1, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0.75 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 0.9 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 8, + "y": 0 + }, + "id": 26, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "8.0.6", + "targets": [ + { + "expr": "min((node_filesystem_size_bytes{fstype=~\"xfs|ext4\",instance=~\"$node\"} - node_filesystem_free_bytes{fstype=~\"xfs|ext4\",instance=~\"$node\"} )/ node_filesystem_size_bytes{fstype=~\"xfs|ext4\",instance=~\"$node\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "/", + "refId": "A", + "step": 1800 + } + ], + "title": "Disk space /", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 70 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 12, + "y": 0 + }, + "id": 25, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "8.0.6", + "targets": [ + { + "expr": "((node_memory_MemTotal_bytes{instance=~\"$node\"} - node_memory_MemAvailable_bytes{instance=~\"$node\"}) / node_memory_MemTotal_bytes{instance=~\"$node\"}) * 100", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "refId": "A", + "step": 1800 + } + ], + "title": "Memory", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 500000000, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 400000000 + }, + { + "color": "rgba(245, 54, 54, 0.9)" + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 16, + "y": 0 + }, + "id": 30, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "8.0.6", + "targets": [ + { + "expr": "(node_memory_SwapTotal_bytes{instance=~'$node'} - node_memory_SwapFree_bytes{instance=~'$node'})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A", + "step": 1800 + } + ], + "title": "Swap", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(69, 193, 31)", + "mode": "fixed" + }, + "decimals": 0, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(245, 54, 54, 0.9)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0.8 + }, + { + "color": "rgba(50, 172, 45, 0.97)", + "value": 0.9 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 20, + "y": 0 + }, + "id": 27, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.0.6", + "targets": [ + { + "expr": "node_load1{instance=~\"$node\"} / count by(job, instance)(count by(job, instance, cpu)(node_cpu_seconds_total{instance=~\"$node\"}))", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "refId": "A", + "step": 1800 + }, + { + "expr": "sum(node_load1{instance=~\"$node\"}) by (instance) / count(node_cpu_seconds_total{mode=\"system\",instance=~\"$node\"}) by (instance) * 100", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Load1", + "refId": "B" + } + ], + "title": "Load1", + "type": "stat" + }, + { + "aliasColors": { + "SENT": "#BF1B00" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 6, + "w": 4, + "x": 0, + "y": 4 + }, + "hiddenSeries": false, + "id": 19, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.6", + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(container_network_receive_bytes_total{id=\"/\",instance=~\"$node\"}[5m])) by (id)", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "RECEIVED", + "refId": "A", + "step": 600 + }, + { + "expr": "- sum(rate(container_network_transmit_bytes_total{id=\"/\",instance=~\"$node\"}[5m ])) by (id)", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "SENT", + "refId": "B", + "step": 600 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": false, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "{id=\"/\",instance=\"cadvisor:8080\",job=\"prometheus\"}": "#BA43A9" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 6, + "w": 4, + "x": 4, + "y": 4 + }, + "hiddenSeries": false, + "id": 5, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(container_cpu_system_seconds_total[1m]))", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "a", + "refId": "B", + "step": 120 + }, + { + "expr": "sum(rate(container_cpu_system_seconds_total{name=~\".+\"}[1m]))", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 2, + "legendFormat": "nur container", + "refId": "F", + "step": 10 + }, + { + "expr": "sum(rate(container_cpu_system_seconds_total{id=\"/\"}[1m]))", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 2, + "legendFormat": "nur docker host", + "metric": "", + "refId": "A", + "step": 20 + }, + { + "expr": "sum(rate(process_cpu_seconds_total[$interval])) * 100", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 2, + "legendFormat": "host", + "metric": "", + "refId": "C", + "step": 600 + }, + { + "expr": "sum(rate(container_cpu_system_seconds_total{name=~\".+\"}[1m])) + sum(rate(container_cpu_system_seconds_total{id=\"/\"}[1m])) + sum(rate(process_cpu_seconds_total[1m]))", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "D", + "step": 120 + }, + { + "expr": "100 - (avg by (instance) (irate(node_cpu_seconds_total{instance=~\"$node\",mode=\"idle\"}[5m])) * 100)", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": false, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1.25 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "0m", + "frequency": "60s", + "handler": 1, + "name": "Panel Title alert", + "noDataState": "keep_state", + "notifications": [ + { + "id": 1 + } + ] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "decimals": 0, + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 4, + "x": 8, + "y": 4 + }, + "hiddenSeries": false, + "id": 28, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_load1{instance=~\"$node\"} / count by(job, instance)(count by(job, instance, cpu)(node_cpu_seconds_total{instance=~\"$node\"}))", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "refId": "A", + "step": 600 + }, + { + "expr": "sum(node_load1{instance=~\"$node\"}) by (instance) / count(node_cpu_seconds_total{mode=\"system\",instance=~\"$node\"}) by (instance) * 100", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "refId": "B" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 1.25, + "visible": true + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Load 1", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": false, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": null, + "logBase": 1, + "max": "300", + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 250000000000 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "frequency": "60s", + "handler": 1, + "name": "Free/Used Disk Space alert", + "noDataState": "keep_state", + "notifications": [ + { + "id": 1 + } + ] + }, + "aliasColors": { + "Belegete Festplatte": "#BF1B00", + "Free Disk Space": "#7EB26D", + "Used Disk Space": "#7EB26D", + "{}": "#BF1B00" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 6, + "w": 4, + "x": 12, + "y": 4 + }, + "hiddenSeries": false, + "id": 13, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Used Disk Space", + "yaxis": 1 + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "node_filesystem_size_bytes{fstype=\"ext4\",instance=~\"$node\"} - node_filesystem_free_bytes{fstype=\"ext4\",instance=~\"$node\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Used Disk Space", + "refId": "A", + "step": 600 + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 250000000000, + "visible": true + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Used Disk Space /", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": false, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": "295279001600", + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 214748364800 + ], + "type": "gt" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "frequency": "60s", + "handler": 1, + "name": "Available Memory alert", + "noDataState": "keep_state", + "notifications": [ + { + "id": 1 + } + ] + }, + "aliasColors": { + "Available Memory": "#7EB26D", + "Unavailable Memory": "#7EB26D" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 6, + "w": 4, + "x": 16, + "y": 4 + }, + "hiddenSeries": false, + "id": 20, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "container_memory_rss{name=~\".+\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "{{__name__}}", + "refId": "D", + "step": 20 + }, + { + "expr": "sum(container_memory_rss{name=~\".+\"})", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "{{__name__}}", + "refId": "A", + "step": 20 + }, + { + "expr": "container_memory_usage_bytes{name=~\".+\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "{{name}}", + "refId": "B", + "step": 20 + }, + { + "expr": "container_memory_rss{id=\"/\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "{{__name__}}", + "refId": "C", + "step": 20 + }, + { + "expr": "sum(container_memory_rss)", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "{{__name__}}", + "refId": "E", + "step": 20 + }, + { + "expr": "node_memory_Buffers", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "node_memory_Dirty", + "refId": "N", + "step": 30 + }, + { + "expr": "node_memory_MemFree", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "{{__name__}}", + "refId": "F", + "step": 20 + }, + { + "expr": "node_memory_MemAvailable", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "Available Memory", + "refId": "H", + "step": 20 + }, + { + "expr": "node_memory_MemTotal_bytes{instance=~\"$node\"} - node_memory_MemAvailable_bytes{instance=~\"$node\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "Unavailable Memory", + "refId": "G", + "step": 600 + }, + { + "expr": "node_memory_Inactive", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "{{__name__}}", + "refId": "I", + "step": 30 + }, + { + "expr": "node_memory_KernelStack", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "{{__name__}}", + "refId": "J", + "step": 30 + }, + { + "expr": "node_memory_Active", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "{{__name__}}", + "refId": "K", + "step": 30 + }, + { + "expr": "node_memory_MemTotal - (node_memory_Active + node_memory_MemFree + node_memory_Inactive)", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "Unknown", + "refId": "L", + "step": 40 + }, + { + "expr": "node_memory_MemFree + node_memory_Inactive ", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "{{__name__}}", + "refId": "M", + "step": 30 + }, + { + "expr": "container_memory_rss{name=~\".+\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "{{__name__}}", + "refId": "O", + "step": 30 + }, + { + "expr": "node_memory_MemAvailable_bytes{instance=~\"$node\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Available memory", + "refId": "P", + "step": 40 + }, + { + "expr": "node_memory_MemFree_bytes{instance=~\"$node\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Free memory", + "refId": "Q" + }, + { + "expr": "node_memory_MemTotal_bytes{instance=~\"$node\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Total memory", + "refId": "R" + }, + { + "expr": "node_memory_MemTotal_bytes{instance=~\"$node\"}-(node_memory_Buffers_bytes{instance=~\"$node\"}+node_memory_Cached_bytes{instance=~\"$node\"}+node_memory_MemFree_bytes{instance=~\"$node\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Used memory", + "refId": "S" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 214748364800, + "visible": true + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Available Memory", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": false, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": "269509197824", + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "IN on /sda": "#7EB26D", + "OUT on /sda": "#890F02" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 6, + "w": 4, + "x": 20, + "y": 4 + }, + "hiddenSeries": false, + "id": 3, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "-sum(rate(node_disk_read_bytes_total{instance=~\"$node\"}[5m])) by (device)", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "OUT on /{{device}}", + "metric": "node_disk_bytes_read", + "refId": "A", + "step": 600 + }, + { + "expr": "sum(rate(node_disk_written_bytes_total{instance=~\"$node\"}[5m])) by (device)", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "IN on /{{device}}", + "metric": "", + "refId": "B", + "step": 600 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk I/O", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": false, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 10 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(container_network_receive_bytes_total{name!=\"\",instance=~\"$node\"}[5m])", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{name}}", + "refId": "A", + "step": 240 + }, + { + "expr": "sum(rate(container_network_transmit_bytes_total{instance=~\"$node\"}[5m])) by (name)", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Received Network Traffic per Container", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "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", + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 10 + }, + "hiddenSeries": false, + "id": 9, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(container_network_transmit_bytes_total{name!=\"\",instance=~\"$node\"}[5m])) by (name)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{name}}", + "refId": "A", + "step": 240 + }, + { + "expr": "rate(container_network_transmit_bytes_total{id=\"/\"}[$interval])", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sent Network Traffic per Container", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": "", + "logBase": 10, + "max": 8, + "min": 0, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "editable": true, + "error": false, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 17 + }, + "hiddenSeries": false, + "id": 1, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(container_cpu_usage_seconds_total{name=~\".+\",instance=~\"$node\"}[5m])) by (name) * 100", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{name}}", + "metric": "", + "refId": "F", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Usage per Container", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": "", + "logBase": 1, + "max": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "editable": true, + "error": false, + "fill": 3, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 25 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.0.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(container_memory_rss{name!=\"\",instance=~\"$node\"}) by (name)", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{name}}", + "refId": "A", + "step": 240 + }, + { + "expr": "container_memory_usage_bytes{name=~\".+\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "{{name}}", + "refId": "B", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "RSS Memory Usage per Container", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "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": 7, + "w": 24, + "x": 0, + "y": 32 + }, + "hiddenSeries": false, + "id": 38, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sort": "avg", + "sortDesc": true, + "total": false, + "values": true + }, + "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": "container_memory_usage_bytes{name!=\"\",instance=~\"$node\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{name}}", + "refId": "A", + "target": "" + }, + { + "expr": "container_spec_memory_limit_bytes{name!=\"\",instance=~\"$node\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "Limit {{name}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Used Memory per Container", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "decimals": 1, + "format": "bytes", + "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": 7, + "w": 24, + "x": 0, + "y": 39 + }, + "hiddenSeries": false, + "id": 40, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "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": "container_memory_usage_bytes{name!=\"\",instance=~\"$node\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "{{name}}", + "refId": "A", + "target": "" + }, + { + "expr": "container_spec_memory_limit_bytes{name!=\"\",instance=~\"$node\"}-container_memory_usage_bytes{name!=\"\",instance=~\"$node\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{name}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Available Memory per Container", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "decimals": 1, + "format": "bytes", + "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": 7, + "w": 24, + "x": 0, + "y": 46 + }, + "hiddenSeries": false, + "id": 39, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "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": "container_memory_usage_bytes{name!=\"\",instance=~\"$node\"}", + "format": "time_series", + "hide": true, + "intervalFactor": 2, + "legendFormat": "Used {{name}}", + "refId": "A", + "target": "" + }, + { + "expr": "container_spec_memory_limit_bytes{name!=\"\",instance=~\"$node\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{name}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Limit Memory per Container", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "decimals": 1, + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "columns": [], + "datasource": "Prometheus", + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 53 + }, + "id": 42, + "links": [], + "pageSize": null, + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "__name__", + "thresholds": [], + "type": "hidden", + "unit": "short" + }, + { + "alias": "Used memory", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #A", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Available memory", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #B", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Limit memory", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Value #C", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Time", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "max(container_memory_usage_bytes{name!=\"\",instance=~\"$node\"}) by (name)", + "format": "table", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + }, + { + "expr": "max(container_memory_max_usage_bytes{name!=\"\",instance=~\"$node\"}-container_memory_usage_bytes{name!=\"\",instance=~\"$node\"})by (name)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "B" + }, + { + "expr": "max(container_memory_max_usage_bytes{name!=\"\",instance=~\"$node\"}) by (name)", + "format": "table", + "instant": true, + "intervalFactor": 1, + "refId": "C" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Memory usage per container", + "transform": "table", + "type": "table-old" + } + ], + "refresh": "5m", + "schemaVersion": 30, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "description": null, + "error": null, + "hide": 2, + "label": "datacenter", + "name": "datacenter", + "query": "IAD*", + "skipUrlSync": false, + "type": "constant" + }, + { + "allValue": null, + "current": { + "isNone": true, + "selected": false, + "text": "None", + "value": "" + }, + "datasource": "Prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "environment", + "options": [], + "query": { + "query": "label_values(cadvisor_version_info, env)", + "refId": "Prometheus-environment-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": "Prometheus", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Job", + "multi": true, + "name": "job", + "options": [], + "query": { + "query": "label_values(cadvisor_version_info, job)", + "refId": "Prometheus-job-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "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(cadvisor_version_info{env=~\"$environment\",job=~\"$job\"}, instance)", + "refId": "Prometheus-node-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": null, + "tagsQuery": null, + "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": "browser", + "title": "Docker and OS metrics ( cadvisor, node_exporter )", + "uid": "Ss3q6hSZk", + "version": 6 +} diff --git a/services/monitoring.jean-cloud.net/installer.sh b/services/monitoring.jean-cloud.net/installer.sh new file mode 100755 index 0000000..91a95fc --- /dev/null +++ b/services/monitoring.jean-cloud.net/installer.sh @@ -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 + + + diff --git a/services/monitoring.jean-cloud.net/nginx_server.conf b/services/monitoring.jean-cloud.net/nginx_server.conf new file mode 100644 index 0000000..4e344a6 --- /dev/null +++ b/services/monitoring.jean-cloud.net/nginx_server.conf @@ -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; + } +} diff --git a/services/monitoring.jean-cloud.net/prometheus.yml b/services/monitoring.jean-cloud.net/prometheus.yml new file mode 100644 index 0000000..8b01c76 --- /dev/null +++ b/services/monitoring.jean-cloud.net/prometheus.yml @@ -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=` 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 + + diff --git a/services/mux.paj.oma-radio.fr/.env b/services/mux.paj.oma-radio.fr/.env index ba5550d..8a88482 100644 --- a/services/mux.paj.oma-radio.fr/.env +++ b/services/mux.paj.oma-radio.fr/.env @@ -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 diff --git a/services/mux.paj.oma-radio.fr/deploy.sh b/services/mux.paj.oma-radio.fr/deploy.sh index f0f4f28..7401d57 100755 --- a/services/mux.paj.oma-radio.fr/deploy.sh +++ b/services/mux.paj.oma-radio.fr/deploy.sh @@ -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 diff --git a/services/mux.paj.oma-radio.fr/docker-compose.yml b/services/mux.paj.oma-radio.fr/docker-compose.yml index 72147b4..d8f9ca1 100644 --- a/services/mux.paj.oma-radio.fr/docker-compose.yml +++ b/services/mux.paj.oma-radio.fr/docker-compose.yml @@ -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: diff --git a/services/mux.paj.oma-radio.fr/nginx_server.conf b/services/mux.paj.oma-radio.fr/nginx_server.conf index aaa83ed..a4a49fe 100644 --- a/services/mux.paj.oma-radio.fr/nginx_server.conf +++ b/services/mux.paj.oma-radio.fr/nginx_server.conf @@ -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; } + } diff --git a/services/mux.radiodemo.oma-radio.fr/.env b/services/mux.radiodemo.oma-radio.fr/.env deleted file mode 100644 index 3ea1179..0000000 --- a/services/mux.radiodemo.oma-radio.fr/.env +++ /dev/null @@ -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 diff --git a/services/mux.radiodemo.oma-radio.fr/deploy.sh b/services/mux.radiodemo.oma-radio.fr/deploy.sh deleted file mode 100755 index 59caf4d..0000000 --- a/services/mux.radiodemo.oma-radio.fr/deploy.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -mkdir -p "$DATA_DIR/pige" -chown 10000:10000 "$DATA_DIR/pige" -R - diff --git a/services/mux.radiodemo.oma-radio.fr/liquidsoap.liq b/services/mux.radiodemo.oma-radio.fr/liquidsoap.liq deleted file mode 120000 index 9c3f58b..0000000 --- a/services/mux.radiodemo.oma-radio.fr/liquidsoap.liq +++ /dev/null @@ -1 +0,0 @@ -liquidsoap-transcode.liq \ No newline at end of file diff --git a/services/mux.radiodemo.oma-radio.fr/server.sh b/services/mux.radiodemo.oma-radio.fr/server.sh deleted file mode 100755 index 7723f2e..0000000 --- a/services/mux.radiodemo.oma-radio.fr/server.sh +++ /dev/null @@ -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 - diff --git a/services/mux.radiokipik.org/nginx_server.conf b/services/mux.radiokipik.org/nginx_server.conf index 778fda6..67149eb 100644 --- a/services/mux.radiokipik.org/nginx_server.conf +++ b/services/mux.radiokipik.org/nginx_server.conf @@ -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; diff --git a/services/nuage.jean-cloud.net/docker-compose.yml b/services/nuage.jean-cloud.net/docker-compose.yml index 393c1b8..033a5a8 100755 --- a/services/nuage.jean-cloud.net/docker-compose.yml +++ b/services/nuage.jean-cloud.net/docker-compose.yml @@ -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: diff --git a/services/nuage.jean-cloud.net/nginx_server.conf b/services/nuage.jean-cloud.net/nginx_server.conf index c9a3fc9..8c9bc87 100755 --- a/services/nuage.jean-cloud.net/nginx_server.conf +++ b/services/nuage.jean-cloud.net/nginx_server.conf @@ -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 diff --git a/services/nuage.jean-cloud.net/zzz-fpm-additional-config.conf b/services/nuage.jean-cloud.net/zzz-fpm-additional-config.conf new file mode 100644 index 0000000..aa4e660 --- /dev/null +++ b/services/nuage.jean-cloud.net/zzz-fpm-additional-config.conf @@ -0,0 +1,2 @@ +[www] +pm.max_children = 10 diff --git a/services/paj.oma-radio.fr.old/.env b/services/paj.oma-radio.fr.old/.env new file mode 100644 index 0000000..e6a7d15 --- /dev/null +++ b/services/paj.oma-radio.fr.old/.env @@ -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" diff --git a/services/paj.oma-radio.fr/.known_hosts b/services/paj.oma-radio.fr.old/.known_hosts similarity index 100% rename from services/paj.oma-radio.fr/.known_hosts rename to services/paj.oma-radio.fr.old/.known_hosts diff --git a/services/paj.oma-radio.fr.old/deploy_user.sh b/services/paj.oma-radio.fr.old/deploy_user.sh new file mode 100755 index 0000000..c0bf6d6 --- /dev/null +++ b/services/paj.oma-radio.fr.old/deploy_user.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -euo pipefail + +# Si le site a déjà été build par le passé, curl termine l’exécution du script en cas d’absence 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 diff --git a/services/paj.oma-radio.fr.old/nginx_server.conf b/services/paj.oma-radio.fr.old/nginx_server.conf new file mode 100755 index 0000000..6f5482a --- /dev/null +++ b/services/paj.oma-radio.fr.old/nginx_server.conf @@ -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; + } +} diff --git a/services/paj.oma-radio.fr/server.sh b/services/paj.oma-radio.fr.old/server.sh similarity index 100% rename from services/paj.oma-radio.fr/server.sh rename to services/paj.oma-radio.fr.old/server.sh diff --git a/services/paj.oma-radio.fr/.env b/services/paj.oma-radio.fr/.env index 8f41d0c..d0dcdb3 100644 --- a/services/paj.oma-radio.fr/.env +++ b/services/paj.oma-radio.fr/.env @@ -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 diff --git a/services/paj.oma-radio.fr/deploy_user.sh b/services/paj.oma-radio.fr/deploy_user.sh index c0bf6d6..9cb4f70 100755 --- a/services/paj.oma-radio.fr/deploy_user.sh +++ b/services/paj.oma-radio.fr/deploy_user.sh @@ -1,19 +1,16 @@ #!/bin/bash -set -euo pipefail -# Si le site a déjà été build par le passé, curl termine l’exécution du script en cas d’absence 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 "$DATA_DIR/.env" < "$DATA_DIR/.env" <>>>>>> 9f3b59b (next step) } diff --git a/services/radiodev.oma-radio.fr/.env b/services/radiodev.oma-radio.fr/.env new file mode 100644 index 0000000..543ca04 --- /dev/null +++ b/services/radiodev.oma-radio.fr/.env @@ -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 diff --git a/services/radiokipik.org/.known_hosts b/services/radiodev.oma-radio.fr/.known_hosts similarity index 100% rename from services/radiokipik.org/.known_hosts rename to services/radiodev.oma-radio.fr/.known_hosts diff --git a/services/mux.radiodemo.oma-radio.fr/deploy_user.sh b/services/radiodev.oma-radio.fr/deploy_user.sh similarity index 69% rename from services/mux.radiodemo.oma-radio.fr/deploy_user.sh rename to services/radiodev.oma-radio.fr/deploy_user.sh index c906f23..9cb4f70 100755 --- a/services/mux.radiodemo.oma-radio.fr/deploy_user.sh +++ b/services/radiodev.oma-radio.fr/deploy_user.sh @@ -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 "$DATA_DIR/.env" < 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 diff --git a/services/mux.radiodemo.oma-radio.fr/liquidsoap-mux.liq b/services/radiodev.oma-radio.fr/liquidsoap-mux.liq similarity index 100% rename from services/mux.radiodemo.oma-radio.fr/liquidsoap-mux.liq rename to services/radiodev.oma-radio.fr/liquidsoap-mux.liq diff --git a/services/radiodev.oma-radio.fr/liquidsoap.liq b/services/radiodev.oma-radio.fr/liquidsoap.liq new file mode 100644 index 0000000..f22fbc2 --- /dev/null +++ b/services/radiodev.oma-radio.fr/liquidsoap.liq @@ -0,0 +1,82 @@ +#!/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"))) + +# Transcode +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() diff --git a/services/mux.radiodemo.oma-radio.fr/nginx_server.conf b/services/radiodev.oma-radio.fr/nginx_server.conf old mode 100644 new mode 100755 similarity index 66% rename from services/mux.radiodemo.oma-radio.fr/nginx_server.conf rename to services/radiodev.oma-radio.fr/nginx_server.conf index e2c4d76..c0e1042 --- a/services/mux.radiodemo.oma-radio.fr/nginx_server.conf +++ b/services/radiodev.oma-radio.fr/nginx_server.conf @@ -19,32 +19,66 @@ 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; - server_name $JC_SERVICE; + 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; + add_header Cache-Control 'max-age=0, must-revalidate'; + } + location / { - client_max_body_size 0; - proxy_pass http://$SOUNDBASE_IP/; - proxy_set_header Host '$SOUNDBASE_HOST'; - proxy_redirect http://$SOUNDBASE_HOST https://$JC_SERVICE; - # wait + try_files $uri $uri/ =404; + add_header Cache-Control 'max-age=0, must-revalidate'; + } + + location /soundbase { + alias "$DATA_DIR/soundbase"; + try_files $uri $uri/ =404; + add_header Cache-Control 'max-age=0, must-revalidate'; + } + + 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 /pige { - alias "$SOUNDBASE_DIR/pige"; - try_files $uri $uri/ =404; - } location /direct.ogg { @@ -62,11 +96,11 @@ server { 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 /style.css { + location /icecast/style.css { client_max_body_size 0; proxy_pass http://$NET$ICECAST:8000/style.css; } - location /status.xsl { + location /icecast/status.xsl { client_max_body_size 0; proxy_pass http://$NET$ICECAST:8000/status.xsl; # kill cache @@ -77,24 +111,7 @@ 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 /manager { + return 301 https://$SOUNDBASE_HOST/manager; } } diff --git a/services/radiokipik.org/.env b/services/radiokipik.org/.env index e38d45b..eff6e7a 100644 --- a/services/radiokipik.org/.env +++ b/services/radiokipik.org/.env @@ -1,5 +1,15 @@ -GIT_SOURCE_REPO="git@gitlab.com:omaradio/website.git" -RADIO_HOST=mux.radiokipik.org -USE_SSL=true WEBSOCKET_PORT=2005 -RADIO_NAME_PRETTY="Radio Kipik" +WEBSERVER=.105 +MUX=.100 +TELECOM=.101 +SWEBSOCKET_PORT=2005 +WEBSOCKET_PORT=2205 +MUX_SERVER_PORT=9005 +TELECOM_SERVER_PORT=3495 +OMA_DOCKER_VERSION=recette +ICECAST=.110 +SOUNDBASE_HOST=soundbase.radiokipik.org +COMPOSE_NAME=radiokipikorg +DOCKER_INSTANCES_PREFIX=radiokipikorg- +DOCKER_INSTANCES_SUFIX=-1 +OMA_CONFIG_LogLevel=8 diff --git a/services/radiokipik.org/deploy_user.sh b/services/radiokipik.org/deploy_user.sh deleted file mode 120000 index e723ae7..0000000 --- a/services/radiokipik.org/deploy_user.sh +++ /dev/null @@ -1 +0,0 @@ -../hugo/deploy_user.sh \ No newline at end of file diff --git a/services/radiokipik.org/deploy_user.sh b/services/radiokipik.org/deploy_user.sh new file mode 100755 index 0000000..9cb4f70 --- /dev/null +++ b/services/radiokipik.org/deploy_user.sh @@ -0,0 +1,16 @@ +#!/bin/bash + + +if [ ! -f "$DATA_DIR/.env" ] ; then + set +e + # head returns 141 on sigpipe + source_pass="$(LC_ALL=C tr -dc A-Za-z0-9 "$DATA_DIR/.env" <&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 diff --git a/services/radiokipik.org/liquidsoap.liq b/services/radiokipik.org/liquidsoap.liq new file mode 100644 index 0000000..fdd9d41 --- /dev/null +++ b/services/radiokipik.org/liquidsoap.liq @@ -0,0 +1,82 @@ +#!/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"))) + +# Icecast +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() diff --git a/services/radiokipik.org/nginx_server.conf b/services/radiokipik.org/nginx_server.conf index 78ae46b..2846dc1 100755 --- a/services/radiokipik.org/nginx_server.conf +++ b/services/radiokipik.org/nginx_server.conf @@ -1,26 +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; - } +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; + } } diff --git a/services/radionimaitre.oma-radio.fr/.env b/services/radionimaitre.oma-radio.fr/.env new file mode 100644 index 0000000..b4ecfcf --- /dev/null +++ b/services/radionimaitre.oma-radio.fr/.env @@ -0,0 +1,17 @@ +TZ=Europe/Paris +OMA_DOCKER_VERSION=latest +WEBSOCKET_PORT=2003 +TELECOM_SERVER_PORT=3493 +MUX_SERVER_PORT=9003 +RADIO_NAME_SIMPLE=radionimaitre +OMA_CONFIG_NomRadio=radionimaitre +RADIO_NAME_PRETTY="Radio Nimaître" +RADIO_HOST=radionimaitre.oma-radio.fr +COMPOSE_NAME=radionimaitreoma-radiofr +DOCKER_INSTANCES_PREFIX=radionimaitreoma-radiofr- +DOCKER_INSTANCES_SUFIX=-1 +DATA_DIR=/data/radionimaitre.oma-radio.fr +SOUNDBASE_DIR=/data/radionimaitre.oma-radio.fr/soundbase/ +USE_SSL=true +PUBLIC_WEBSITE_UPSTREAM=https://static.oma-radio.fr/player-interface/1.5.0 +MANAGER_WEBSITE_UPSTREAM=https://static.oma-radio.fr/single-manager/1.1.1 diff --git a/services/radionimaitre.oma-radio.fr/docker-compose.yml b/services/radionimaitre.oma-radio.fr/docker-compose.yml new file mode 100644 index 0000000..78e2655 --- /dev/null +++ b/services/radionimaitre.oma-radio.fr/docker-compose.yml @@ -0,0 +1,177 @@ +version: '3' +services: + ambre_mux: + image: jeancloud/mux:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_CONFIG_Client1Host: 172.29.3.110 + OMA_CONFIG_TelecommandeHost: 172.29.3.101 + volumes: + - $SOUNDBASE_DIR/pige:/app/pige + ports: + - $MUX_SERVER_PORT:9000 + restart: unless-stopped + networks: + default: + ipv4_address: 172.29.3.100 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M + + + saphir_telecom_server: + image: jeancloud/telecom-server:$OMA_DOCKER_VERSION + env_file: .env + ports: + - $TELECOM_SERVER_PORT:3490 + restart: unless-stopped + networks: + default: + ipv4_address: 172.29.3.101 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M + + anthracite_jukebox: + image: jeancloud/jukebox:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_CONFIG_TelecommandeHost: 172.29.3.101 + OMA_CONFIG_Client1Host: 172.29.3.100 + volumes: + - $SOUNDBASE_DIR:/app/soundBase + - $DATA_DIR/secours-jingle.wavM:/app/secours/secours-jingle.wavM + restart: unless-stopped + networks: + default: + ipv4_address: 172.29.3.102 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M + + azurite_jukebox_simulator: + image: jeancloud/jukebox-simulator:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_CONFIG_TelecommandeHost: 172.29.3.101 + volumes: + - $SOUNDBASE_DIR:/app/soundBase + restart: unless-stopped + networks: + default: + ipv4_address: 172.29.3.103 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M + + # aventurine_transcode: + # image: jeancloud/transcode:$OMA_DOCKER_VERSION + # env_file: .env + # restart: unless-stopped + + + agate_importer: + image: jeancloud/baseimport:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_CONFIG_TelecommandeHost: 172.29.3.101 + volumes: + - $SOUNDBASE_DIR:/app/soundBase + restart: unless-stopped + networks: + default: + ipv4_address: 172.29.3.104 + deploy: + resources: + limits: + cpus: '0.50' + memory: 500M + + amarante_webserver: + image: jeancloud/webserver:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_CONFIG_TelecommandeHost: 172.29.3.101 + OMA_CONFIG_PigeTxtLoadFic: off + restart: unless-stopped + volumes: + - $SOUNDBASE_DIR:/soundbase + networks: + default: + ipv4_address: 172.29.3.105 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M + + + system_api: + image: jeancloud/system-api:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_CONFIG_TelecommandeHost: 172.29.3.101 + UID: 33 + SOUNDBASE_PATH: /soundbase + MOUNT: /api + CONFIG_PATH: /config + restart: unless-stopped + volumes: + - /tmp/uwsgi/$RADIO_HOST:/tmp/uwsgi + - /var/run/docker.sock:/var/run/docker.sock + - $SOUNDBASE_DIR:/soundbase + networks: + default: + ipv4_address: 172.29.3.107 + deploy: + resources: + limits: + cpus: '0.50' + memory: 500M + + transcode: + image: jeancloud/liquidsoap:1.3.7 + env_file: .env + volumes: + - ./transcode.liq:/transcode.liq + command: /transcode.liq + restart: unless-stopped + networks: + default: + ipv4_address: 172.29.3.108 + + icecast: + image: jeancloud/icecast:alpine-2.4.0 + restart: unless-stopped + environment: + # echo -n "source:pass" | base64 + ICECAST_SOURCE_PASSWORD: JsCabjWJUZXrrrKCaaRZma5wD4YKj5LQLXv6f + ICECAST_ADMIN_PASSWORD: STh5LrPMvp876KPoajCPEUpehE98JPqZ6sEixSnzJ42CR2MdyPMBYfzjGpbAzajNgw8jsuLh + ICECAST_RELAY_PASSWORD: r2LgmDocgyYh7DqhSsey8tM99wxdViTpLtyi9tcWHtokC73QnC6kQLRRb58VUy5FXYnStRsG + ICECAST_ADMIN_USERNAME: admin + ICECAST_ADMIN_EMAIL: contact@oma-radio.fr + ICECAST_LOCATION: Rhône-Alpes + TZ: Europe/Paris + healthcheck: + test: "wget http://localhost:8000/direct.ogg -O - -t 1 -T 3 -S --spider 2>&1 | grep '200 OK' && wget http://localhost:8000/direct.mp3 -O - -t 1 -T 3 -S --spider 2>&1 | grep '200 OK'" + interval: 5m0s + timeout: 10s + retries: 3 + start_period: 1m0s + networks: + default: + ipv4_address: 172.29.3.110 + +networks: + default: + ipam: + config: + - subnet: 172.29.3.0/24 diff --git a/services/radionimaitre.oma-radio.fr/nginx_server.conf b/services/radionimaitre.oma-radio.fr/nginx_server.conf new file mode 100644 index 0000000..068c22b --- /dev/null +++ b/services/radionimaitre.oma-radio.fr/nginx_server.conf @@ -0,0 +1,231 @@ +# Parameters: +# radio name +# file path +# ws port (local) +# wss port (open) +# upload service port +# ssl certs location + +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +server{ + listen $WEBSOCKET_PORT ssl; + listen [::]:$WEBSOCKET_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://172.29.3.105:9000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_read_timeout 120s; + } +} + +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name $RADIO_HOST www.$RADIO_HOST; + ssl_certificate $JC_CERT/fullchain.pem; + ssl_certificate_key $JC_CERT/privkey.pem; + + root $SOUNDBASE_DIR/website; + index index.html; + + location = /direct.ogg { + proxy_pass http://172.29.3.110: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 { + proxy_pass http://172.29.3.110:8000/direct.mp3; + # 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 = /api { rewrite ^ /api/; } + location ~ /api/pigeindex(/.*) { + include uwsgi_params; + uwsgi_param PATH_INFO "/pigeindex$1"; + uwsgi_param SCRIPT_NAME /api; + uwsgi_pass unix:/tmp/uwsgi/$RADIO_HOST/uwsgi-api.sock; + client_max_body_size 0; + uwsgi_connect_timeout 6000; + uwsgi_send_timeout 6000; + uwsgi_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://radio.karnaval.fr; + if_modified_since off; + expires off; + etag off; + + } + location ~ /api(/.*) { + 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 /api; + uwsgi_pass unix:/tmp/uwsgi/$RADIO_HOST/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 /pige{ + alias $SOUNDBASE_DIR/pige; + try_files $uri $uri/ =404; + } + location /pigeMp3{ + alias $SOUNDBASE_DIR/pigeMp3; + try_files $uri $uri/ =404; + } + location /png { + alias $SOUNDBASE_DIR/png; + try_files $uri $uri/ =404; + } + location /webpL { + alias $SOUNDBASE_DIR/webpL; + try_files $uri $uri/ =404; + } + location /webpH { + alias $SOUNDBASE_DIR/webpH; + try_files $uri $uri/ =404; + } + location /ogg { + alias $SOUNDBASE_DIR/ogg; + try_files $uri $uri/ =404; + } + location /txt { + # 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; + alias $SOUNDBASE_DIR/txt; + try_files $uri $uri/ =404; + } + location /wavM { + # 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; + alias $SOUNDBASE_DIR/wavM; + try_files $uri $uri/ =404; + } + location /import { + # 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; + alias $SOUNDBASE_DIR/import; + try_files $uri $uri/ =404; + } + location /export { + # 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; + alias $SOUNDBASE_DIR/export; + try_files $uri $uri/ =404; + } + location /wav { + # 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; + alias $SOUNDBASE_DIR/wav; + try_files $uri $uri/ =404; + } + location /fiches { + alias $SOUNDBASE_DIR/fiches; + try_files $uri $uri/ =404; + # 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 /prg { + # 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; + alias $SOUNDBASE_DIR/prg; + try_files $uri $uri/ =404; + } + location /listes { + # 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; + alias $SOUNDBASE_DIR/listes; + try_files $uri $uri/ =404; + } + location /statique { + alias $SOUNDBASE_DIR/statique; + try_files $uri $uri/ =404; + # 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; + } + + # Admin interface + location /manager { + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; + try_files $uri $uri/ =404; + } + location = /favicon.ico { + return 301 /favicon.webp; + } + + # for js, css, html — dynamic site, players + location / { + try_files $uri $uri/ =404; + add_header Cache-Control 'public must-revalidate'; + } +} diff --git a/services/radionimaitre.oma-radio.fr/radioking.liq b/services/radionimaitre.oma-radio.fr/radioking.liq new file mode 100644 index 0000000..2bd23f4 --- /dev/null +++ b/services/radionimaitre.oma-radio.fr/radioking.liq @@ -0,0 +1,7 @@ +input = mksafe(input.http("http://172.29.0.110:8000/direct.mp3")) +output.icecast( + %mp3(bitrate=128, samplerate=22050, stereo=false), + mount="/test355", + host="live.radioking.com", port=80, user="test_test29", password="S9tx3VBhl", + input) + diff --git a/services/radionimaitre.oma-radio.fr/transcode.liq b/services/radionimaitre.oma-radio.fr/transcode.liq new file mode 100644 index 0000000..11befca --- /dev/null +++ b/services/radionimaitre.oma-radio.fr/transcode.liq @@ -0,0 +1,11 @@ +#!/usr/bin/liquidsoap + +input = mksafe(input.http("http://icecast:8000/direct.ogg")) +#blank = single("/secours.ogg") +#input = fallback(track_sensitive=false, [input, blank]) +output.icecast( + %mp3(bitrate=128, samplerate=22050, stereo=false), + mount="/direct.mp3", + host="icecast", port=8000, password="JsCabjWJUZXrrrKCaaRZma5wD4YKj5LQLXv6f", + input) + diff --git a/services/secours.paj.oma-radio.fr/.env b/services/secours.paj.oma-radio.fr/.env new file mode 100644 index 0000000..58bcaf7 --- /dev/null +++ b/services/secours.paj.oma-radio.fr/.env @@ -0,0 +1,13 @@ +TZ=Europe/Paris +OMA_DOCKER_VERSION=recette +WEBSOCKET_PORT=2002 +TELECOM_SERVER_PORT=3492 +OMA_FORCE_TelecommandeHost=paj.oma-radio.fr +OMA_FORCE_TelecommandePort=3492 +MUX_SERVER_PORT=9002 +RADIO_NAME_SIMPLE=paj +OMA_FORCE_NomRadio=paj +OMA_FORCE_LogLevel=8 +RADIO_NAME_PRETTY="Paj radio" +USE_SSL=true +RADIO_HOST=paj.oma-radio.fr diff --git a/services/secours.paj.oma-radio.fr/deploy_user.sh b/services/secours.paj.oma-radio.fr/deploy_user.sh new file mode 100755 index 0000000..57e03d7 --- /dev/null +++ b/services/secours.paj.oma-radio.fr/deploy_user.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +mkdir -p "$DATA_DIR/soundbase/" "$DATA_DIR/.ssh" + +cat > "$DATA_DIR/.ssh/authorized_keys" < "$DATA_DIR/.ssh/authorized_keys" < "$DATA_DIR/tete.fingerprint" +fi + +mkdir -p ~/.ssh +cat > ~/.ssh/known_hosts <> ~/.ssh/known_hosts + +echo "Generate ssh key if needed" +if [ ! -e "$DATA_DIR/.ssh/synchro_tete.sshkey" ] ; then + ssh-keygen -f "$DATA_DIR/.ssh/synchro_tete.sshkey" -N '' +fi + +mkdir -p "$DATA_DIR/soundbase" + +echo "Sync manager files" +rclone sync --config=/notfound --sftp-host sftp.jean-cloud.net --sftp-user "staticRO" --sftp-port 2929 --sftp-key-file "$SECRET_DIR/static.sshkey" ":sftp:/static/manager/$OMA_DOCKER_VERSION" "$DATA_DIR/soundbase/manager/" + +echo "Sync player files" +rclone sync --config=/notfound --sftp-host sftp.jean-cloud.net --sftp-user "staticRO" --sftp-port 2929 --sftp-key-file "$SECRET_DIR/static.sshkey" ":sftp:/static/player/$OMA_DOCKER_VERSION" "$DATA_DIR/soundbase/player/" + +#echo "copy index to have nice url" +#sed -e "s/%%RADIO_NAME_PRETTY%%/$RADIO_NAME_PRETTY/g" -e "s/%%WEBSOCKET_PORT%%/$WEBSOCKET_PORT/g" "$DATA_DIR/soundbase/player/index.html" > "$DATA_DIR/soundbase/index.html" + +"$DOCKER_DIR/regen_website.sh" diff --git a/services/soundbase.paj.oma-radio.fr/docker-compose.yml b/services/soundbase.paj.oma-radio.fr/docker-compose.yml index eb0ff3c..1144c22 100644 --- a/services/soundbase.paj.oma-radio.fr/docker-compose.yml +++ b/services/soundbase.paj.oma-radio.fr/docker-compose.yml @@ -1,16 +1,17 @@ version: '3' services: - anthracite_jukebox: + jukebox: image: registry.gitlab.com/omaradio/core/oma-jukebox:$OMA_DOCKER_VERSION env_file: .env environment: - OMA_CONFIG_TelecommandeHost: $RADIO_HOST - OMA_CONFIG_TelecommandePort: $TELECOM_SERVER_PORT - OMA_CONFIG_Client1Host: $RADIO_HOST - OMA_CONFIG_Client1Port: $MUX_SERVER_PORT + OMA_FORCE_TelecommandeHost: $RADIO_HOST + OMA_FORCE_TelecommandePort: $TELECOM_SERVER_PORT + OMA_FORCE_Client1Host: $RADIO_HOST + OMA_FORCE_Client1Port: $MUX_SERVER_PORT volumes: - - $DATA_DIR:/app/soundBase - - $DATA_DIR/secours-jingle.wavM:/app/secours/secours-jingle.wavM + - $DATA_DIR/soundbase:/app/soundBase + - $DATA_DIR/soundbase/secours/JingleDemo-Secours.wavM:/app/secours/secours-jingle.wavM + restart: unless-stopped networks: default: @@ -18,39 +19,18 @@ services: deploy: resources: limits: - cpus: '0.50' + cpus: '1' memory: 100M - azurite_jukebox_simulator: - image: registry.gitlab.com/omaradio/core/oma-jukebox-simulator:$OMA_DOCKER_VERSION + + importer: + image: registry.gitlab.com/omaradio/core/oma-base-import:$OMA_DOCKER_VERSION env_file: .env environment: - OMA_CONFIG_TelecommandeHost: $RADIO_HOST + OMA_FORCE_TelecommandeHost: $RADIO_HOST volumes: - - $DATA_DIR:/app/soundBase - restart: unless-stopped - networks: - default: - ipv4_address: $NET.103 - deploy: - resources: - limits: - cpus: '0.50' - memory: 100M - - # aventurine_transcode: - # image: jeancloud/transcode:$OMA_DOCKER_VERSION - # env_file: .env - # restart: unless-stopped - - - agate_importer: - image: registry.gitlab.com/omaradio/core/oma-baseimport:$OMA_DOCKER_VERSION - env_file: .env - environment: - OMA_CONFIG_TelecommandeHost: $RADIO_HOST - volumes: - - $DATA_DIR:/app/soundBase + - $DATA_DIR/soundbase:/app/soundBase + stop_grace_period: 1m30s restart: unless-stopped networks: default: @@ -62,14 +42,14 @@ services: memory: 1000M - rubis_base_mg: + basemg: image: registry.gitlab.com/omaradio/core/oma-base-mg:$OMA_DOCKER_VERSION env_file: .env environment: - OMA_CONFIG_TelecommandeHost: $RADIO_HOST + OMA_FORCE_TelecommandeHost: $RADIO_HOST restart: unless-stopped volumes: - - $DATA_DIR:/soundbase + - $DATA_DIR/soundbase:/soundbase networks: default: ipv4_address: $NET.106 @@ -81,10 +61,10 @@ services: system_api: - image: jeancloud/system-api:dev + image: jeancloud/system-api:$OMA_DOCKER_VERSION env_file: .env environment: - OMA_CONFIG_TelecommandeHost: $RADIO_HOST + OMA_FORCE_TelecommandeHost: $RADIO_HOST UID: 33 SOUNDBASE_PATH: /soundbase MOUNT: /api @@ -93,7 +73,7 @@ services: volumes: - /tmp/uwsgi/$JC_SERVICE:/tmp/uwsgi - /var/run/docker.sock:/var/run/docker.sock - - $DATA_DIR:/soundbase + - $DATA_DIR/soundbase:/soundbase networks: default: ipv4_address: $NET.107 @@ -102,34 +82,24 @@ services: limits: cpus: '0.50' memory: 500M + mp3addon: + image: registry.gitlab.com/omaradio/core/oma-mp3-addon:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_FORCE_TelecommandeHost: $RADIO_HOST + restart: unless-stopped + volumes: + - $DATA_DIR/soundbase:/app/soundBase + networks: + default: + ipv4_address: $NET.108 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M - #ammolite_mp3_addon: - # image: jeancloud/mp3addon:$OMA_DOCKER_VERSION - # env_file: .env - # environment: - # OMA_CONFIG_TelecommandeHost: $NET.101 - # OMA_CONFIG_PigePrefix: /opt - # restart: unless-stopped - # volumes: - # - $DATA_DIR:/app/soundbase - # networks: - # default: - # ipv4_address: $NET.109 - # deploy: - # resources: - # limits: - # cpus: '0.05' - - # doxy: - # image: qnib/doxy - # volumes: - # - /tmp/radiodemo.oma-radio.fr/doxy:/tmp/doxy - # - /data/radiodemo.oma-radio.fr/doxy.pattern:/etc/doxy.pattern - # - /var/run/docker.sock:/var/run/docker.sock - # environment: - # DOXY_PROXY_SOCKET: /tmp/doxy/doxy.sock - networks: default: ipam: diff --git a/services/soundbase.paj.oma-radio.fr/lsyncd.conf b/services/soundbase.paj.oma-radio.fr/lsyncd.conf new file mode 100644 index 0000000..724644c --- /dev/null +++ b/services/soundbase.paj.oma-radio.fr/lsyncd.conf @@ -0,0 +1,17 @@ +settings { + logfile = "$TMP_DIR/lsyncd.log", + statusFile = "$TMP_DIR/lsyncd.status", + nodaemon = true, +} + +sync { + default.rsyncssh, + source = "$DATA_DIR/soundbase", + host = "$LSYNCD_HOST", + targetdir = "$LSYNCD_TARGET", + exclude = {'wav*/*', 'png/*', 'jpg*/*', 'png*/*', 'txt/*', 'webpH/*', 'import*/*', 'bonus*', 'prg/*', 'secours/*', 'statique/*', 'pige/*'}, + ssh = { + identityFile = "~/.ssh/synchro_tete.sshkey", + port = 45985, + }, +} diff --git a/services/soundbase.paj.oma-radio.fr/nginx_server.conf b/services/soundbase.paj.oma-radio.fr/nginx_server.conf index 2761cf8..a57ee57 100644 --- a/services/soundbase.paj.oma-radio.fr/nginx_server.conf +++ b/services/soundbase.paj.oma-radio.fr/nginx_server.conf @@ -16,16 +16,33 @@ server { - listen 80; - listen [::]:80; + listen 443 ssl; + listen [::]:443 ssl; server_name $JC_SERVICE; - root $HTTP_DIR/manager/dist; - index index.html; + ssl_certificate $JC_CERT/fullchain.pem; + ssl_certificate_key $JC_CERT/privkey.pem; + + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $DATA_DIR/soundbase/users.htpasswd; + + location /soundbase/fic { + alias $DATA_DIR/soundbase/fic; + index index.html; + # 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 /soundbase { + alias $DATA_DIR/soundbase; + index index.html; + } location ~ /api(/.*) { - 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 /api; @@ -43,77 +60,10 @@ server { etag off; } - location /pige{ - alias $SOUNDBASE_DIR/pige; - try_files $uri $uri/ =404; - } - location /png { - alias $SOUNDBASE_DIR/png; - try_files $uri $uri/ =404; - } - location /webpL { - alias $SOUNDBASE_DIR/webpL; - try_files $uri $uri/ =404; - } - location /webpH { - alias $SOUNDBASE_DIR/webpH; - try_files $uri $uri/ =404; - } - location /ogg { - alias $SOUNDBASE_DIR/ogg; - try_files $uri $uri/ =404; - } - location /txt { - alias $SOUNDBASE_DIR/txt; - try_files $uri $uri/ =404; - } - location /wavM { - auth_basic "Entrez votre identifiant et mot de passe"; - auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; - alias $SOUNDBASE_DIR/wavM; - try_files $uri $uri/ =404; - } - location /import { - auth_basic "Entrez votre identifiant et mot de passe"; - auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; - alias $SOUNDBASE_DIR/import; - try_files $uri $uri/ =404; - } - location /export { - auth_basic "Entrez votre identifiant et mot de passe"; - auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; - alias $SOUNDBASE_DIR/export; - try_files $uri $uri/ =404; - } - location /wav { - auth_basic "Entrez votre identifiant et mot de passe"; - auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; - alias $SOUNDBASE_DIR/wav; - try_files $uri $uri/ =404; - } - location /fic { - add_header Cache-Control "must-revalidate, proxy-revalidate"; - alias $SOUNDBASE_DIR/fic; - try_files $uri $uri/ =404; - } - location /prg { - auth_basic "Entrez votre identifiant et mot de passe"; - auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; - alias $SOUNDBASE_DIR/prg; - try_files $uri $uri/ =404; - } - location /lst { - auth_basic "Entrez votre identifiant et mot de passe"; - auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; - alias $SOUNDBASE_DIR/lst; - try_files $uri $uri/ =404; - } # Admin interface location /manager { - alias $HTTP_DIR/manager/dist; - auth_basic "Entrez votre identifiant et mot de passe"; - auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; + alias $DATA_DIR/soundbase/manager; try_files $uri $uri/ =404; } } diff --git a/services/soundbase.paj.oma-radio.fr/regen_website.sh b/services/soundbase.paj.oma-radio.fr/regen_website.sh new file mode 100755 index 0000000..3a25e1f --- /dev/null +++ b/services/soundbase.paj.oma-radio.fr/regen_website.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -euo pipefail + + + +echo "Generate website" +if [ -e "$DATA_DIR/soundbase/fic/_website-_config.fic" ] ; then + "omarustwebsite-$OMA_DOCKER_VERSION" --soundbase-path $DATA_DIR/soundbase --output $DATA_DIR/soundbase/website/ --soundbase-prefix '/soundbase' --website-prefix '' --manager-url "https://$JC_SERVICE/manager" --player-url '/soundbase/player' --websocket-port "$WEBSOCKET_PORT" --radio-host "$RADIO_HOST" +fi + +echo "(kill and) start lsyncd with head" +cat "$DOCKER_DIR/lsyncd.conf" | template.sh "$DOCKER_DIR/.env" > "$TMP_DIR/lsyncd.conf" +pid_file="$TMP_DIR/lsyncd.pid" +[ -f "$pid_file" ] && kill "$(cat "$pid_file")" || true +lsyncd "$TMP_DIR/lsyncd.conf" -pidfile "$pid_file" 2>&1 >> "$TMP_DIR/lsyncd.log" & diff --git a/services/soundbase.radiodemo.oma-radio.fr/.env b/services/soundbase.radiodemo.oma-radio.fr/.env index 60f8276..9a7cf09 100644 --- a/services/soundbase.radiodemo.oma-radio.fr/.env +++ b/services/soundbase.radiodemo.oma-radio.fr/.env @@ -1,24 +1,22 @@ -NET=10.29.0 TELECOM=.101 ICECAST=.110 WEBSERVER=.105 SYSTEM_API=.107 TZ=Europe/Paris -OMA_DOCKER_VERSION=dev +OMA_DOCKER_VERSION=recette WEBSOCKET_PORT=2004 TELECOM_SERVER_PORT=3494 -OMA_CONFIG_TelecommandeHost=mux.radiodemo.oma-radio.fr -OMA_CONFIG_TelecommandePort=3494 +OMA_FORCE_TelecommandeHost=radiodemo.oma-radio.fr +OMA_FORCE_TelecommandePort=3494 MUX_SERVER_PORT=9004 RADIO_NAME_SIMPLE=radiodemo -OMA_CONFIG_NomRadio=radiodemo -OMA_CONFIG_LogLevel=8 +OMA_FORCE_NomRadio=radiodemo +OMA_FORCE_LogLevel=8 RADIO_NAME_PRETTY="Radio Démo" COMPOSE_NAME=soundbaseradiodemooma-radiofr DOCKER_INSTANCES_PREFIX=soundbaseradiodemooma-radiofr- DOCKER_INSTANCES_SUFIX=-1 -SOUNDBASE_DIR=/data/soundbase.radiodemo.oma-radio.fr/core/radioDemo USE_SSL=true -MANAGER_VERSION=3.0.0 -PUBLIC_WEBSITE_UPSTREAM=https://static.oma-radio.fr/player-interface/1.1.1 RADIO_HOST=radiodemo.oma-radio.fr +LSYNCD_HOST="radiodemo.oma-radio.fr@radiodemo.oma-radio.fr" +LSYNCD_TARGET="/data/radiodemo.oma-radio.fr/soundbase" diff --git a/services/soundbase.radiodemo.oma-radio.fr/deploy.sh b/services/soundbase.radiodemo.oma-radio.fr/deploy.sh deleted file mode 100755 index f4948f2..0000000 --- a/services/soundbase.radiodemo.oma-radio.fr/deploy.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -apt install -y nodejs npm -#docker run --rm -i -v /srv/http/soundbase.radiodemo.oma-radio.fr:/app node:alpine sh < "$DATA_DIR/tete.fingerprint" +fi + mkdir -p ~/.ssh cat > ~/.ssh/known_hosts <> ~/.ssh/known_hosts - -echo "Pull demo git" -if [ -d "$DATA_DIR/core" ] ; then - git_update.sh -r dev -o "-i $DATA_DIR/radiodemo-deploy" -d "$DATA_DIR/core" git@gitlab.com:omaradio/core.git +echo "Generate ssh key if needed" +if [ ! -e "$DATA_DIR/.ssh/synchro_tete.sshkey" ] ; then + ssh-keygen -f "$DATA_DIR/.ssh/synchro_tete.sshkey" -N '' fi +mkdir -p "$DATA_DIR/soundbase" +chown "$USER:syncthing.oma-radio.fr" "$DATA_DIR/soundbase" +chmod 775 "$DATA_DIR/soundbase" echo "Sync manager files" -mkdir -p "$DATA_DIR/soundbase/manager" rclone sync --config=/notfound --sftp-host sftp.jean-cloud.net --sftp-user "staticRO" --sftp-port 2929 --sftp-key-file "$SECRET_DIR/static.sshkey" ":sftp:/static/manager/$OMA_DOCKER_VERSION" "$DATA_DIR/soundbase/manager/" echo "Sync player files" -mkdir -p "$DATA_DIR/soundbase/player" rclone sync --config=/notfound --sftp-host sftp.jean-cloud.net --sftp-user "staticRO" --sftp-port 2929 --sftp-key-file "$SECRET_DIR/static.sshkey" ":sftp:/static/player/$OMA_DOCKER_VERSION" "$DATA_DIR/soundbase/player/" -echo "Generate website" -omarustwebsite-dev --soundbase-path "$SOUNDBASE_DIR" --output "$SOUNDBASE_DIR/website/" --soundbase-prefix '/soundbase' --website-prefix "" --player-url '/soundbase/player' +#echo "copy index to have nice url" +#sed -e "s/%%RADIO_NAME_PRETTY%%/$RADIO_NAME_PRETTY/g" -e "s/%%WEBSOCKET_PORT%%/$WEBSOCKET_PORT/g" "$DATA_DIR/soundbase/player/index.html" > "$DATA_DIR/soundbase/index.html" -echo "starting lsyncd" -pkill "lsyncd" || true -mkdir -p /tmp/jc_log -chmod 777 /tmp/jc_log || true -lsyncd "$DOCKER_DIR/lsyncd.conf" 2>&1 >>/tmp/jc_log/$JC_SERVICE.lsyncd.log & +"$DOCKER_DIR/regen_website.sh" + + +echo "Template lsyncd" +if [ "$DOCKER_DIR/lsyncd.conf" -nt "$TMP_DIR/lsyncd.conf" ] ; then + echo " need update" + cat "$DOCKER_DIR/lsyncd.conf" | template.sh "$DOCKER_DIR/.env" > "$TMP_DIR/lsyncd.conf" +fi + +echo "Check for lsyncd" +pid_file="$TMP_DIR/lsyncd.pid" +touch "$pid_file" +killall -u lsyncd || true +ps --pid "$(cat "$pid_file")" &>/dev/null || \ + ( echo " need start" && \ + lsyncd "$TMP_DIR/lsyncd.conf" -pidfile "$pid_file" 2>&1 >> "$TMP_DIR/lsyncd.log" & \ + ) diff --git a/services/soundbase.radiodemo.oma-radio.fr/docker-compose.yml b/services/soundbase.radiodemo.oma-radio.fr/docker-compose.yml index e49840a..4baba19 100644 --- a/services/soundbase.radiodemo.oma-radio.fr/docker-compose.yml +++ b/services/soundbase.radiodemo.oma-radio.fr/docker-compose.yml @@ -4,13 +4,13 @@ services: image: registry.gitlab.com/omaradio/core/oma-jukebox:$OMA_DOCKER_VERSION env_file: .env environment: - OMA_CONFIG_TelecommandeHost: $RADIO_HOST - OMA_CONFIG_TelecommandePort: $TELECOM_SERVER_PORT - OMA_CONFIG_Client1Host: $RADIO_HOST - OMA_CONFIG_Client1Port: $MUX_SERVER_PORT + OMA_FORCE_TelecommandeHost: $RADIO_HOST + OMA_FORCE_TelecommandePort: $TELECOM_SERVER_PORT + OMA_FORCE_Client1Host: $RADIO_HOST + OMA_FORCE_Client1Port: $MUX_SERVER_PORT volumes: - - $SOUNDBASE_DIR:/app/soundBase - - $SOUNDBASE_DIR/secours/JingleDemo-Secours.wavM:/app/secours/secours-jingle.wavM + - $DATA_DIR/soundbase:/app/soundBase + - $DATA_DIR/soundbase/secours/JingleDemo-Secours.wavM:/app/secours/secours-jingle.wavM restart: unless-stopped networks: @@ -29,7 +29,8 @@ services: environment: OMA_CONFIG_TelecommandeHost: $RADIO_HOST volumes: - - $SOUNDBASE_DIR:/app/soundBase + - $DATA_DIR/soundbase:/app/soundBase + - /data/core.oma-radio.fr/bonus-$OMA_DOCKER_VERSION:/app/core stop_grace_period: 1m30s restart: unless-stopped networks: @@ -49,7 +50,8 @@ services: OMA_CONFIG_TelecommandeHost: $RADIO_HOST restart: unless-stopped volumes: - - $SOUNDBASE_DIR:/soundbase + - $DATA_DIR/soundbase:/soundbase + - /data/core.oma-radio.fr/bonus-$OMA_DOCKER_VERSION:/app/core/ networks: default: ipv4_address: $NET.106 @@ -73,7 +75,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 @@ -82,6 +84,22 @@ services: limits: cpus: '0.50' memory: 500M + mp3addon: + image: registry.gitlab.com/omaradio/core/oma-mp3-addon:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_CONFIG_TelecommandeHost: $RADIO_HOST + restart: unless-stopped + volumes: + - $DATA_DIR/soundbase:/app/soundBase + networks: + default: + ipv4_address: $NET.108 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M networks: default: diff --git a/services/soundbase.radiodemo.oma-radio.fr/lsyncd.conf b/services/soundbase.radiodemo.oma-radio.fr/lsyncd.conf index b7d334c..724644c 100644 --- a/services/soundbase.radiodemo.oma-radio.fr/lsyncd.conf +++ b/services/soundbase.radiodemo.oma-radio.fr/lsyncd.conf @@ -1,21 +1,17 @@ settings { - logfile = "/tmp/lsyncd.log", - statusFile = "/tmp/lsyncd.status", + logfile = "$TMP_DIR/lsyncd.log", + statusFile = "$TMP_DIR/lsyncd.status", nodaemon = true, } sync { default.rsyncssh, - source = "/data/soundbase.radiodemo.oma-radio.fr/soundbase", - host = "radiodemo.oma-radio.fr@radiodemo.oma-radio.fr", - targetdir = "/data/radiodemo.oma-radio.fr/soundbase", - exclude = {'/wav*', '/png/', '/jpg*', '/png*', '/txt/', '/webpH/', '/import*', '/fic', '/bonus*', '/prg/', '/secours/', '/statique/', '/tmp/', '/cart/', 'cfg_*', '/readme.md', '/mp3/', '/lst/', '/groups.json', '/users.htpasswd'}, + source = "$DATA_DIR/soundbase", + host = "$LSYNCD_HOST", + targetdir = "$LSYNCD_TARGET", + exclude = {'wav*/*', 'png/*', 'jpg*/*', 'png*/*', 'txt/*', 'webpH/*', 'import*/*', 'bonus*', 'prg/*', 'secours/*', 'statique/*', 'pige/*'}, ssh = { identityFile = "~/.ssh/synchro_tete.sshkey", port = 45985, }, - -- need 2.3.0 -- daily sync - --crontab = { - -- "11 11 4 * * *", - --}, } diff --git a/services/soundbase.radiodemo.oma-radio.fr/nginx_server.conf b/services/soundbase.radiodemo.oma-radio.fr/nginx_server.conf index 1133752..7e7d998 100644 --- a/services/soundbase.radiodemo.oma-radio.fr/nginx_server.conf +++ b/services/soundbase.radiodemo.oma-radio.fr/nginx_server.conf @@ -22,6 +22,7 @@ server { ssl_certificate $JC_CERT/fullchain.pem; ssl_certificate_key $JC_CERT/privkey.pem; +<<<<<<< HEAD root $SOUNDBASE_DIR; index index.html; @@ -38,6 +39,34 @@ server { try_files $uri $uri/ =404; } +======= + + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $DATA_DIR/soundbase/users.htpasswd; + + location /soundbase/fic { + alias $DATA_DIR/soundbase/fic; + index index.html; + # 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 /soundbase { + alias $DATA_DIR/soundbase; + index index.html; + } + + location /buildwebsite/ { + fastcgi_param SCRIPT_FILENAME $DOCKER_DIR/server.sh; + fastcgi_pass unix:/var/run/fcgiwrap.socket; + } + + +>>>>>>> 9f3b59b (next step) location ~ /api(/.*) { include uwsgi_params; uwsgi_param PATH_INFO "$1"; @@ -57,4 +86,12 @@ server { } +<<<<<<< HEAD +======= + # Admin interface + location /manager { + alias $DATA_DIR/soundbase/manager; + try_files $uri $uri/ =404; + } +>>>>>>> 9f3b59b (next step) } diff --git a/services/soundbase.radiodemo.oma-radio.fr/regen_website.sh b/services/soundbase.radiodemo.oma-radio.fr/regen_website.sh new file mode 100755 index 0000000..3a25e1f --- /dev/null +++ b/services/soundbase.radiodemo.oma-radio.fr/regen_website.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -euo pipefail + + + +echo "Generate website" +if [ -e "$DATA_DIR/soundbase/fic/_website-_config.fic" ] ; then + "omarustwebsite-$OMA_DOCKER_VERSION" --soundbase-path $DATA_DIR/soundbase --output $DATA_DIR/soundbase/website/ --soundbase-prefix '/soundbase' --website-prefix '' --manager-url "https://$JC_SERVICE/manager" --player-url '/soundbase/player' --websocket-port "$WEBSOCKET_PORT" --radio-host "$RADIO_HOST" +fi + +echo "(kill and) start lsyncd with head" +cat "$DOCKER_DIR/lsyncd.conf" | template.sh "$DOCKER_DIR/.env" > "$TMP_DIR/lsyncd.conf" +pid_file="$TMP_DIR/lsyncd.pid" +[ -f "$pid_file" ] && kill "$(cat "$pid_file")" || true +lsyncd "$TMP_DIR/lsyncd.conf" -pidfile "$pid_file" 2>&1 >> "$TMP_DIR/lsyncd.log" & diff --git a/services/soundbase.radiodev.oma-radio.fr/.env b/services/soundbase.radiodev.oma-radio.fr/.env new file mode 100644 index 0000000..48ab09f --- /dev/null +++ b/services/soundbase.radiodev.oma-radio.fr/.env @@ -0,0 +1,24 @@ +TELECOM=.101 +ICECAST=.110 +WEBSERVER=.105 +SYSTEM_API=.107 +TZ=Europe/Paris +OMA_DOCKER_VERSION=dev +WEBSOCKET_PORT=2006 +TELECOM_SERVER_PORT=3496 +OMA_FORCE_TelecommandeHost=176.190.114.89 +OMA_FORCE_TelecommandePort=3496 +MUX_SERVER_PORT=9006 +RADIO_NAME_SIMPLE=radiodev +OMA_FORCE_NomRadio=radiodev +OMA_FORCE_LogLevel=8 +RADIO_NAME_PRETTY="Radio Dev" +COMPOSE_NAME=soundbaseradiodevoma-radiofr +DOCKER_INSTANCES_PREFIX=soundbaseradiodevoma-radiofr- +DOCKER_INSTANCES_SUFIX=-1 +USE_SSL=true +RADIO_HOST=radiodev.oma-radio.fr +# Les softs cpp ne peuvent par résoudre le DNS +RADIO_HOST_IP=176.190.114.89 +LSYNCD_HOST="radiodev.oma-radio.fr@radiodev.oma-radio.fr" +LSYNCD_TARGET="/data/radiodev.oma-radio.fr/soundbase" diff --git a/services/soundbase.radiodev.oma-radio.fr/deploy_user.sh b/services/soundbase.radiodev.oma-radio.fr/deploy_user.sh new file mode 100755 index 0000000..41528a6 --- /dev/null +++ b/services/soundbase.radiodev.oma-radio.fr/deploy_user.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +set -euo pipefail + + + +echo "Add ssh fingerprints" +if [ ! -e "$DATA_DIR/tete.fingerprint" ] ; then + ssh-keyscan -p 45985 "$RADIO_HOST" > "$DATA_DIR/tete.fingerprint" +fi + +mkdir -p ~/.ssh +cat > ~/.ssh/known_hosts <> ~/.ssh/known_hosts + +echo "Generate ssh key if needed" +if [ ! -e "$DATA_DIR/.ssh/synchro_tete.sshkey" ] ; then + ssh-keygen -f "$DATA_DIR/.ssh/synchro_tete.sshkey" -N '' +fi + +mkdir -p "$DATA_DIR/soundbase" +chown "$USER:syncthing.oma-radio.fr" "$DATA_DIR/soundbase" +chmod 775 "$DATA_DIR/soundbase" + +echo "Sync manager files" +rclone sync --config=/notfound --sftp-host sftp.jean-cloud.net --sftp-user "staticRO" --sftp-port 2929 --sftp-key-file "$SECRET_DIR/static.sshkey" ":sftp:/static/manager/$OMA_DOCKER_VERSION" "$DATA_DIR/soundbase/manager/" + +echo "Sync player files" +rclone sync --config=/notfound --sftp-host sftp.jean-cloud.net --sftp-user "staticRO" --sftp-port 2929 --sftp-key-file "$SECRET_DIR/static.sshkey" ":sftp:/static/player/$OMA_DOCKER_VERSION" "$DATA_DIR/soundbase/player/" + +#echo "copy index to have nice url" +#sed -e "s/%%RADIO_NAME_PRETTY%%/$RADIO_NAME_PRETTY/g" -e "s/%%WEBSOCKET_PORT%%/$WEBSOCKET_PORT/g" "$DATA_DIR/soundbase/player/index.html" > "$DATA_DIR/soundbase/index.html" + +"$DOCKER_DIR/regen_website.sh" + + +echo "Template lsyncd" +cat "$DOCKER_DIR/lsyncd.conf" | template.sh "$DOCKER_DIR/.env" > "$TMP_DIR/lsyncd.conf" + +echo "Check for lsyncd" +pid_file="$TMP_DIR/lsyncd.pid" +touch "$pid_file" +killall -u "$USER" lsyncd || true +ps --pid "$(cat "$pid_file")" &>/dev/null || \ + ( echo " need start" && \ + lsyncd "$TMP_DIR/lsyncd.conf" -pidfile "$pid_file" 2>&1 >> "$TMP_DIR/lsyncd.log" & \ + ) diff --git a/services/soundbase.radiodev.oma-radio.fr/docker-compose.yml b/services/soundbase.radiodev.oma-radio.fr/docker-compose.yml new file mode 100644 index 0000000..87863c6 --- /dev/null +++ b/services/soundbase.radiodev.oma-radio.fr/docker-compose.yml @@ -0,0 +1,119 @@ +version: '3' +services: + jukebox: + image: registry.gitlab.com/omaradio/core/oma-jukebox:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_FORCE_Client1Host: $RADIO_HOST_IP + OMA_FORCE_Client1Port: $MUX_SERVER_PORT + volumes: + - $DATA_DIR/soundbase:/app/soundBase + - $DATA_DIR/secours-jingle.wavM:/app/secours/secours-jingle.wavM + + restart: unless-stopped + networks: + default: + ipv4_address: $NET.102 + deploy: + resources: + limits: + cpus: '1' + memory: 100M + + + importer: + image: registry.gitlab.com/omaradio/core/oma-base-import:$OMA_DOCKER_VERSION + env_file: .env + volumes: + - $DATA_DIR/soundbase:/app/soundBase + - /data/core.oma-radio.fr/bonus-$OMA_DOCKER_VERSION:/app/core + stop_grace_period: 1m30s + restart: unless-stopped + networks: + default: + ipv4_address: $NET.104 + deploy: + resources: + limits: + cpus: '0.50' + memory: 1000M + + + basemg: + image: registry.gitlab.com/omaradio/core/oma-base-mg:$OMA_DOCKER_VERSION + env_file: .env + volumes: + - $DATA_DIR/soundbase:/soundbase + - /data/core.oma-radio.fr/bonus-$OMA_DOCKER_VERSION:/app/core/ + stop_grace_period: 1m30s + restart: unless-stopped + networks: + default: + ipv4_address: $NET.106 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M + + + system_api: + image: jeancloud/system-api:$OMA_DOCKER_VERSION + env_file: .env + environment: + UID: 33 + SOUNDBASE_PATH: /soundbase + MOUNT: /api + 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 + mp3addon: + image: registry.gitlab.com/omaradio/core/oma-mp3-addon:$OMA_DOCKER_VERSION + env_file: .env + restart: unless-stopped + volumes: + - $DATA_DIR/soundbase:/app/soundBase + networks: + default: + ipv4_address: $NET.108 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M + + player: + image: registry.gitlab.com/omaradio/core/oma-player:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_FORCE_Client1Port: 80 + OMA_FORCE_Client1Host: radiodev.oma-radio.fr + restart: unless-stopped + volumes: + - $DATA_DIR/soundbase:/app/soundBase + networks: + default: + ipv4_address: $NET.109 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M + + +networks: + default: + ipam: + config: + - subnet: $NET.0/24 diff --git a/services/soundbase.radiodev.oma-radio.fr/lsyncd.conf b/services/soundbase.radiodev.oma-radio.fr/lsyncd.conf new file mode 100644 index 0000000..724644c --- /dev/null +++ b/services/soundbase.radiodev.oma-radio.fr/lsyncd.conf @@ -0,0 +1,17 @@ +settings { + logfile = "$TMP_DIR/lsyncd.log", + statusFile = "$TMP_DIR/lsyncd.status", + nodaemon = true, +} + +sync { + default.rsyncssh, + source = "$DATA_DIR/soundbase", + host = "$LSYNCD_HOST", + targetdir = "$LSYNCD_TARGET", + exclude = {'wav*/*', 'png/*', 'jpg*/*', 'png*/*', 'txt/*', 'webpH/*', 'import*/*', 'bonus*', 'prg/*', 'secours/*', 'statique/*', 'pige/*'}, + ssh = { + identityFile = "~/.ssh/synchro_tete.sshkey", + port = 45985, + }, +} diff --git a/services/soundbase.radiodev.oma-radio.fr/nginx_server.conf b/services/soundbase.radiodev.oma-radio.fr/nginx_server.conf new file mode 100644 index 0000000..2fbe436 --- /dev/null +++ b/services/soundbase.radiodev.oma-radio.fr/nginx_server.conf @@ -0,0 +1,75 @@ +# Parameters: +# radio name +# file path +# ws port (local) +# wss port (open) +# upload service port +# ssl certs location + +# TODO +# /speedtest-down returns random data +# can use : openssl enc -aes-256-ctr -pass pass:"$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64)" -nosalt < /dev/zero > randomfile.bin +# /speedtest-up just eat everything it can + + + + + +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name $JC_SERVICE; + + ssl_certificate $JC_CERT/fullchain.pem; + ssl_certificate_key $JC_CERT/privkey.pem; + + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $DATA_DIR/soundbase/users.htpasswd; + + location /soundbase/fic { + alias $DATA_DIR/soundbase/fic; + index index.html; + # kill cache + add_header Cache-Control 'must-revalidate, proxy-revalidate, max-age=0'; + if_modified_since off; + expires off; + etag off; + } + + location /soundbase { + alias $DATA_DIR/soundbase; + index index.html; + add_header Cache-Control 'must-revalidate, proxy-revalidate, max-age=0'; + } + + location /buildwebsite/ { + fastcgi_param SCRIPT_FILENAME $DOCKER_DIR/server.sh; + fastcgi_pass unix:/var/run/fcgiwrap.socket; + } + + + location ~ /api(/.*) { + 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'; + if_modified_since off; + expires off; + etag off; + } + + + # Admin interface + location /manager { + alias $DATA_DIR/soundbase/manager; + try_files $uri $uri/ =404; + } +} diff --git a/services/soundbase.radiodev.oma-radio.fr/regen_website.sh b/services/soundbase.radiodev.oma-radio.fr/regen_website.sh new file mode 100755 index 0000000..317d4af --- /dev/null +++ b/services/soundbase.radiodev.oma-radio.fr/regen_website.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -euo pipefail + + + +echo "Génération du site web" +"omarustwebsite-$OMA_DOCKER_VERSION" --soundbase-path $DATA_DIR/soundbase --output $DATA_DIR/soundbase/website/ --soundbase-prefix '/soundbase' --website-prefix '' --manager-url "https://$JC_SERVICE/manager" --player-url '/soundbase/player' --websocket-port "$WEBSOCKET_PORT" --radio-host "$RADIO_HOST" + diff --git a/services/soundbase.radiodev.oma-radio.fr/server.sh b/services/soundbase.radiodev.oma-radio.fr/server.sh new file mode 100755 index 0000000..594f76e --- /dev/null +++ b/services/soundbase.radiodev.oma-radio.fr/server.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +echo "Content-type: text/plain; charset=utf-8" +echo "" + +. .env + +deploy_as "$JC_SERVICE" 'regen_website.sh' 2>&1 diff --git a/services/soundbase.radiokipik.org.bak/.env b/services/soundbase.radiokipik.org.bak/.env new file mode 100644 index 0000000..b648d3d --- /dev/null +++ b/services/soundbase.radiokipik.org.bak/.env @@ -0,0 +1,23 @@ +NET=10.29.0 +TELECOM=.101 +ICECAST=.110 +WEBSERVER=.105 +SYSTEM_API=.107 +TZ=Europe/Paris +OMA_DOCKER_VERSION=unstable +WEBSOCKET_PORT=2005 +TELECOM_SERVER_PORT=3495 +OMA_CONFIG_TelecommandeHost=mux.radiokipik.org +OMA_CONFIG_TelecommandePort=3495 +MUX_SERVER_PORT=9005 +RADIO_NAME_SIMPLE=radiokipik +OMA_CONFIG_NomRadio=radiokipik +RADIO_NAME_PRETTY="Radio Kipik" +COMPOSE_NAME=soundbaseradiokipikorg +DOCKER_INSTANCES_PREFIX=soundbaseradiokipikorg- +DOCKER_INSTANCES_SUFIX=-1 +SOUNDBASE_DIR=/data/soundbase.radiokipik.org/soundbase/ +USE_SSL=true +MANAGER_VERSION=3.0.0 +PUBLIC_WEBSITE_UPSTREAM=https://static.oma-radio.fr/player-interface/1.1.1 +RADIO_HOST=radiokipik.org diff --git a/services/soundbase.radiokipik.org/deploy.sh b/services/soundbase.radiokipik.org.bak/deploy.sh similarity index 100% rename from services/soundbase.radiokipik.org/deploy.sh rename to services/soundbase.radiokipik.org.bak/deploy.sh diff --git a/services/soundbase.radiokipik.org.bak/deploy_user.sh b/services/soundbase.radiokipik.org.bak/deploy_user.sh new file mode 100755 index 0000000..0befb8f --- /dev/null +++ b/services/soundbase.radiokipik.org.bak/deploy_user.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +#if [ -d "$DATA_DIR/core" ] ; then +# git_update.sh -b dev -i "$DATA_DIR/gitlab-deploy.sshprivkey" -d "$DATA_DIR/core" git@gitlab.com:omaradio/core.git +#fi + +#chmod 700 "$SECRET_DIR/gitlab-deploy.sshprivkey" +#mkdir -p "$HTTP_DIR/manager" +#git_update.sh -r 'v3.0' -o "-i $SECRET_DIR/gitlab-deploy.sshprivkey" -d "$HTTP_DIR/manager" git@gitlab.com:omaradio/single-manager.git +#cd "$HTTP_DIR/manager" +#npm install +#npm run build + + +#semver_prefix="3." +## Get available versions +#json="$(curl 'https://gitlab.com/api/v4/projects/omaradio%2Fsingle-manager/packages?order_by=version&sort=desc&package_name=manager&status=default' )" +# +## Get the latest one +#latest="$(echo "$json" | grep -Po '"version":"\K'"$semver_prefix"'[^"]+"' | tr -d '"' | sort -g | tail -n 1)" +#if [ -z "$latest" ] ; then +# echo "Version is empty" +# exit 1 +#fi +# +## Get associated link +#link="$(echo "$json" | jq ".[] | select(.version? | match(\"$latest\")) | ._links.web_path" | sed -e 's/^"//' -e 's/"$//')" +#if [ -z "$link" ] ; then +# echo "Link is empty" +# exit 1 +#fi +# +#cd "$HTTP_DIR" + +#wget https://gitlab.com/omaradio/single-manager/-/package_files/117195410/download -O - | tar xz diff --git a/services/soundbase.radiokipik.org.bak/docker-compose.yml b/services/soundbase.radiokipik.org.bak/docker-compose.yml new file mode 100644 index 0000000..0ad6b41 --- /dev/null +++ b/services/soundbase.radiokipik.org.bak/docker-compose.yml @@ -0,0 +1,106 @@ +version: '3' +services: + anthracite_jukebox: + image: registry.gitlab.com/omaradio/core/oma-jukebox:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_CONFIG_Client1Host: mux.radiokipik.org + OMA_CONFIG_Client1Port: $MUX_SERVER_PORT + OMA_CONFIG_Client2: off + OMA_CONFIG_Client2Host: radionimaitre.oma-radio.fr + OMA_CONFIG_Client2Port: 9003 + volumes: + - $SOUNDBASE_DIR:/app/soundBase + - $DATA_DIR/secours-jingle.wavM:/app/secours/secours-jingle.wavM + restart: unless-stopped + networks: + default: + ipv4_address: $NET.102 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M + + azurite_jukebox_simulator: + image: registry.gitlab.com/omaradio/core/oma-jukebox-simulator:$OMA_DOCKER_VERSION + env_file: .env + volumes: + - $SOUNDBASE_DIR:/app/soundBase + restart: unless-stopped + networks: + default: + ipv4_address: $NET.103 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M + + # aventurine_transcode: + # image: jeancloud/transcode:$OMA_DOCKER_VERSION + # env_file: .env + # restart: unless-stopped + + + agate_importer: + image: registry.gitlab.com/omaradio/core/oma-baseimport:$OMA_DOCKER_VERSION + env_file: .env + volumes: + - $SOUNDBASE_DIR:/app/soundBase + restart: unless-stopped + networks: + default: + ipv4_address: $NET.104 + deploy: + resources: + limits: + cpus: '0.50' + memory: 500M + + + rubis_base_mg: + image: registry.gitlab.com/omaradio/core/oma-base-mg:$OMA_DOCKER_VERSION + env_file: .env + restart: unless-stopped + volumes: + - $SOUNDBASE_DIR:/soundbase + networks: + default: + ipv4_address: $NET.106 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M + + + system_api: + image: jeancloud/system-api:dev + env_file: .env + environment: + UID: 33 + SOUNDBASE_PATH: /soundbase + MOUNT: /api + CONFIG_PATH: /config + restart: unless-stopped + volumes: + - /tmp/uwsgi/$JC_SERVICE:/tmp/uwsgi + - /var/run/docker.sock:/var/run/docker.sock + - $SOUNDBASE_DIR:/soundbase + networks: + default: + ipv4_address: $NET.107 + deploy: + resources: + limits: + cpus: '0.50' + memory: 500M + + + +networks: + default: + ipam: + config: + - subnet: $NET.0/24 diff --git a/services/soundbase.radiodemo.oma-radio.fr/generate_nat.sh b/services/soundbase.radiokipik.org.bak/generate_nat.sh similarity index 100% rename from services/soundbase.radiodemo.oma-radio.fr/generate_nat.sh rename to services/soundbase.radiokipik.org.bak/generate_nat.sh diff --git a/services/soundbase.radiokipik.org.bak/nginx_server.conf b/services/soundbase.radiokipik.org.bak/nginx_server.conf new file mode 100644 index 0000000..6a687f7 --- /dev/null +++ b/services/soundbase.radiokipik.org.bak/nginx_server.conf @@ -0,0 +1,119 @@ +# Parameters: +# radio name +# file path +# ws port (local) +# wss port (open) +# upload service port +# ssl certs location + +# TODO +# /speedtest-down returns random data +# can use : openssl enc -aes-256-ctr -pass pass:"$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64)" -nosalt < /dev/zero > randomfile.bin +# /speedtest-up just eat everything it can + + + + + +server { + listen 80; + listen [::]:80; + server_name $JC_SERVICE; + + root $SOUNDBASE_DIR/website; + index index.html; + + location ~ /api(/.*) { + 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 /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'; + if_modified_since off; + expires off; + etag off; + } + + location /pige{ + alias $SOUNDBASE_DIR/pige; + try_files $uri $uri/ =404; + } + location /png { + alias $SOUNDBASE_DIR/png; + try_files $uri $uri/ =404; + } + location /webpL { + alias $SOUNDBASE_DIR/webpL; + try_files $uri $uri/ =404; + } + location /webpH { + alias $SOUNDBASE_DIR/webpH; + try_files $uri $uri/ =404; + } + location /ogg { + alias $SOUNDBASE_DIR/ogg; + try_files $uri $uri/ =404; + } + location /txt { + alias $SOUNDBASE_DIR/txt; + try_files $uri $uri/ =404; + } + location /wavM { + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; + alias $SOUNDBASE_DIR/wavM; + try_files $uri $uri/ =404; + } + location /import { + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; + alias $SOUNDBASE_DIR/import; + try_files $uri $uri/ =404; + } + location /export { + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; + alias $SOUNDBASE_DIR/export; + try_files $uri $uri/ =404; + } + location /wav { + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; + alias $SOUNDBASE_DIR/wav; + try_files $uri $uri/ =404; + } + location /fic { + add_header Cache-Control 'must-revalidate, proxy-revalidate'; + alias $SOUNDBASE_DIR/fic; + try_files $uri $uri/ =404; + } + location /prg { + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; + alias $SOUNDBASE_DIR/prg; + try_files $uri $uri/ =404; + } + location /lst { + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; + alias $SOUNDBASE_DIR/lst; + try_files $uri $uri/ =404; + } + + # Admin interface + location /manager { + alias $HTTP_DIR/manager/dist; + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; + try_files $uri $uri/ =404; + } +} diff --git a/services/soundbase.radiokipik.org/.env b/services/soundbase.radiokipik.org/.env index b648d3d..2f20390 100644 --- a/services/soundbase.radiokipik.org/.env +++ b/services/soundbase.radiokipik.org/.env @@ -1,23 +1,22 @@ -NET=10.29.0 TELECOM=.101 ICECAST=.110 WEBSERVER=.105 SYSTEM_API=.107 TZ=Europe/Paris -OMA_DOCKER_VERSION=unstable +OMA_DOCKER_VERSION=recette WEBSOCKET_PORT=2005 TELECOM_SERVER_PORT=3495 -OMA_CONFIG_TelecommandeHost=mux.radiokipik.org -OMA_CONFIG_TelecommandePort=3495 +OMA_FORCE_TelecommandeHost=radiokipik.org +OMA_FORCE_TelecommandePort=3495 MUX_SERVER_PORT=9005 RADIO_NAME_SIMPLE=radiokipik -OMA_CONFIG_NomRadio=radiokipik +OMA_FORCE_NomRadio=radiokipik +OMA_FORCE_LogLevel=8 RADIO_NAME_PRETTY="Radio Kipik" COMPOSE_NAME=soundbaseradiokipikorg DOCKER_INSTANCES_PREFIX=soundbaseradiokipikorg- DOCKER_INSTANCES_SUFIX=-1 -SOUNDBASE_DIR=/data/soundbase.radiokipik.org/soundbase/ USE_SSL=true -MANAGER_VERSION=3.0.0 -PUBLIC_WEBSITE_UPSTREAM=https://static.oma-radio.fr/player-interface/1.1.1 RADIO_HOST=radiokipik.org +LSYNCD_HOST="radiokipik.org@radiokipik.org" +LSYNCD_TARGET="/data/radiokipik.org/soundbase" diff --git a/services/soundbase.radiokipik.org/deploy_user.sh b/services/soundbase.radiokipik.org/deploy_user.sh index 69920d8..4c8d56f 100755 --- a/services/soundbase.radiokipik.org/deploy_user.sh +++ b/services/soundbase.radiokipik.org/deploy_user.sh @@ -1,35 +1,35 @@ #!/bin/bash -#if [ -d "$DATA_DIR/core" ] ; then -# git_update.sh -b dev -i "$DATA_DIR/gitlab-deploy.sshprivkey" -d "$DATA_DIR/core" git@gitlab.com:omaradio/core.git -#fi - -chmod 700 "$SECRET_DIR/gitlab-deploy.sshprivkey" -mkdir -p "$HTTP_DIR/manager" -git_update.sh -r 'v3.0' -o "-i $SECRET_DIR/gitlab-deploy.sshprivkey" -d "$HTTP_DIR/manager" git@gitlab.com:omaradio/single-manager.git -cd "$HTTP_DIR/manager" -npm install -npm run build +set -euo pipefail -#semver_prefix="3." -## Get available versions -#json="$(curl 'https://gitlab.com/api/v4/projects/omaradio%2Fsingle-manager/packages?order_by=version&sort=desc&package_name=manager&status=default' )" -# -## Get the latest one -#latest="$(echo "$json" | grep -Po '"version":"\K'"$semver_prefix"'[^"]+"' | tr -d '"' | sort -g | tail -n 1)" -#if [ -z "$latest" ] ; then -# echo "Version is empty" -# exit 1 -#fi -# -## Get associated link -#link="$(echo "$json" | jq ".[] | select(.version? | match(\"$latest\")) | ._links.web_path" | sed -e 's/^"//' -e 's/"$//')" -#if [ -z "$link" ] ; then -# echo "Link is empty" -# exit 1 -#fi -# -#cd "$HTTP_DIR" -#wget https://gitlab.com/omaradio/single-manager/-/package_files/117195410/download -O - | tar xz +echo "Add ssh fingerprints" +if [ ! -e "$DATA_DIR/tete.fingerprint" ] ; then + ssh-keyscan -p 45985 "$RADIO_HOST" > "$DATA_DIR/tete.fingerprint" +fi + +mkdir -p ~/.ssh +cat > ~/.ssh/known_hosts <> ~/.ssh/known_hosts + +echo "Generate ssh key if needed" +if [ ! -e "$DATA_DIR/.ssh/synchro_tete.sshkey" ] ; then + ssh-keygen -f "$DATA_DIR/.ssh/synchro_tete.sshkey" -N '' +fi + +mkdir -p "$DATA_DIR/soundbase" + +echo "Sync manager files" +rclone sync --config=/notfound --sftp-host sftp.jean-cloud.net --sftp-user "staticRO" --sftp-port 2929 --sftp-key-file "$SECRET_DIR/static.sshkey" ":sftp:/static/manager/$OMA_DOCKER_VERSION" "$DATA_DIR/soundbase/manager/" + +echo "Sync player files" +rclone sync --config=/notfound --sftp-host sftp.jean-cloud.net --sftp-user "staticRO" --sftp-port 2929 --sftp-key-file "$SECRET_DIR/static.sshkey" ":sftp:/static/player/$OMA_DOCKER_VERSION" "$DATA_DIR/soundbase/player/" + +#echo "copy index to have nice url" +#sed -e "s/%%RADIO_NAME_PRETTY%%/$RADIO_NAME_PRETTY/g" -e "s/%%WEBSOCKET_PORT%%/$WEBSOCKET_PORT/g" "$DATA_DIR/soundbase/player/index.html" > "$DATA_DIR/soundbase/index.html" + +"$DOCKER_DIR/regen_website.sh" diff --git a/services/soundbase.radiokipik.org/docker-compose.yml b/services/soundbase.radiokipik.org/docker-compose.yml index ce573d2..3210fe9 100644 --- a/services/soundbase.radiokipik.org/docker-compose.yml +++ b/services/soundbase.radiokipik.org/docker-compose.yml @@ -1,17 +1,17 @@ version: '3' services: - anthracite_jukebox: + jukebox: image: registry.gitlab.com/omaradio/core/oma-jukebox:$OMA_DOCKER_VERSION env_file: .env environment: - OMA_CONFIG_Client1Host: mux.radiokipik.org - OMA_CONFIG_Client1Port: $MUX_SERVER_PORT - OMA_CONFIG_Client2: off - OMA_CONFIG_Client2Host: radionimaitre.oma-radio.fr - OMA_CONFIG_Client2Port: 9003 + OMA_FORCE_TelecommandeHost: $RADIO_HOST + OMA_FORCE_TelecommandePort: $TELECOM_SERVER_PORT + OMA_FORCE_Client1Host: $RADIO_HOST + OMA_FORCE_Client1Port: $MUX_SERVER_PORT volumes: - - $SOUNDBASE_DIR:/app/soundBase - - $DATA_DIR/secours-jingle.wavM:/app/secours/secours-jingle.wavM + - $DATA_DIR/soundbase:/app/soundBase + - $DATA_DIR/soundbase/secours/JingleDemo-Secours.wavM:/app/secours/secours-jingle.wavM + restart: unless-stopped networks: default: @@ -19,35 +19,18 @@ services: deploy: resources: limits: - cpus: '0.50' + cpus: '1' memory: 100M - azurite_jukebox_simulator: - image: registry.gitlab.com/omaradio/core/oma-jukebox-simulator:$OMA_DOCKER_VERSION + + importer: + image: registry.gitlab.com/omaradio/core/oma-base-import:$OMA_DOCKER_VERSION env_file: .env + environment: + OMA_CONFIG_TelecommandeHost: $RADIO_HOST volumes: - - $SOUNDBASE_DIR:/app/soundBase - restart: unless-stopped - networks: - default: - ipv4_address: $NET.103 - deploy: - resources: - limits: - cpus: '0.50' - memory: 100M - - # aventurine_transcode: - # image: jeancloud/transcode:$OMA_DOCKER_VERSION - # env_file: .env - # restart: unless-stopped - - - agate_importer: - image: registry.gitlab.com/omaradio/core/oma-baseimport:$OMA_DOCKER_VERSION - env_file: .env - volumes: - - $SOUNDBASE_DIR:/app/soundBase + - $DATA_DIR/soundbase:/app/soundBase + stop_grace_period: 1m30s restart: unless-stopped networks: default: @@ -56,15 +39,17 @@ services: resources: limits: cpus: '0.50' - memory: 500M + memory: 1000M - rubis_base_mg: + basemg: image: registry.gitlab.com/omaradio/core/oma-base-mg:$OMA_DOCKER_VERSION env_file: .env + environment: + OMA_CONFIG_TelecommandeHost: $RADIO_HOST restart: unless-stopped volumes: - - $SOUNDBASE_DIR:/soundbase + - $DATA_DIR/soundbase:/soundbase networks: default: ipv4_address: $NET.106 @@ -79,6 +64,7 @@ services: image: jeancloud/system-api:$OMA_DOCKER_VERSION env_file: .env environment: + OMA_CONFIG_TelecommandeHost: $RADIO_HOST UID: 33 SOUNDBASE_PATH: /soundbase MOUNT: /api @@ -87,7 +73,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 @@ -96,7 +82,22 @@ services: limits: cpus: '0.50' memory: 500M - + mp3addon: + image: registry.gitlab.com/omaradio/core/oma-mp3-addon:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_CONFIG_TelecommandeHost: $RADIO_HOST + restart: unless-stopped + volumes: + - $DATA_DIR/soundbase:/app/soundBase + networks: + default: + ipv4_address: $NET.108 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M networks: diff --git a/services/soundbase.radiokipik.org/generate_nat.sh b/services/soundbase.radiokipik.org/generate_nat.sh deleted file mode 100755 index d692df8..0000000 --- a/services/soundbase.radiokipik.org/generate_nat.sh +++ /dev/null @@ -1,20 +0,0 @@ -function extract_ports_from_compose { - if [ "$#" -ne 1 ] ; then - echo "function extract_ports_from_dockerfile needs 1 parameter : docker-compose file" >&2 - exit 1 - fi - ports=false - while read line ; do - if [ "$line" = 'ports:' ] ; then - ports=true - elif "$ports" ; then - if [[ "$line" != -* ]] ; then - ports=false - else - echo $line | tr -d ' ' | tail -c +2 - fi - fi - done < docker-compose.yml -} - -extract_ports_from_compose docker-compose.yml | ../_deployer/template.sh .env diff --git a/services/soundbase.radiokipik.org/lsyncd.conf b/services/soundbase.radiokipik.org/lsyncd.conf new file mode 100644 index 0000000..724644c --- /dev/null +++ b/services/soundbase.radiokipik.org/lsyncd.conf @@ -0,0 +1,17 @@ +settings { + logfile = "$TMP_DIR/lsyncd.log", + statusFile = "$TMP_DIR/lsyncd.status", + nodaemon = true, +} + +sync { + default.rsyncssh, + source = "$DATA_DIR/soundbase", + host = "$LSYNCD_HOST", + targetdir = "$LSYNCD_TARGET", + exclude = {'wav*/*', 'png/*', 'jpg*/*', 'png*/*', 'txt/*', 'webpH/*', 'import*/*', 'bonus*', 'prg/*', 'secours/*', 'statique/*', 'pige/*'}, + ssh = { + identityFile = "~/.ssh/synchro_tete.sshkey", + port = 45985, + }, +} diff --git a/services/soundbase.radiokipik.org/nginx_server.conf b/services/soundbase.radiokipik.org/nginx_server.conf index 6a687f7..a57ee57 100644 --- a/services/soundbase.radiokipik.org/nginx_server.conf +++ b/services/soundbase.radiokipik.org/nginx_server.conf @@ -16,16 +16,33 @@ server { - listen 80; - listen [::]:80; + listen 443 ssl; + listen [::]:443 ssl; server_name $JC_SERVICE; - root $SOUNDBASE_DIR/website; - index index.html; + ssl_certificate $JC_CERT/fullchain.pem; + ssl_certificate_key $JC_CERT/privkey.pem; + + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $DATA_DIR/soundbase/users.htpasswd; + + location /soundbase/fic { + alias $DATA_DIR/soundbase/fic; + index index.html; + # 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 /soundbase { + alias $DATA_DIR/soundbase; + index index.html; + } location ~ /api(/.*) { - 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 /api; @@ -43,77 +60,10 @@ server { etag off; } - location /pige{ - alias $SOUNDBASE_DIR/pige; - try_files $uri $uri/ =404; - } - location /png { - alias $SOUNDBASE_DIR/png; - try_files $uri $uri/ =404; - } - location /webpL { - alias $SOUNDBASE_DIR/webpL; - try_files $uri $uri/ =404; - } - location /webpH { - alias $SOUNDBASE_DIR/webpH; - try_files $uri $uri/ =404; - } - location /ogg { - alias $SOUNDBASE_DIR/ogg; - try_files $uri $uri/ =404; - } - location /txt { - alias $SOUNDBASE_DIR/txt; - try_files $uri $uri/ =404; - } - location /wavM { - auth_basic "Entrez votre identifiant et mot de passe"; - auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; - alias $SOUNDBASE_DIR/wavM; - try_files $uri $uri/ =404; - } - location /import { - auth_basic "Entrez votre identifiant et mot de passe"; - auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; - alias $SOUNDBASE_DIR/import; - try_files $uri $uri/ =404; - } - location /export { - auth_basic "Entrez votre identifiant et mot de passe"; - auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; - alias $SOUNDBASE_DIR/export; - try_files $uri $uri/ =404; - } - location /wav { - auth_basic "Entrez votre identifiant et mot de passe"; - auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; - alias $SOUNDBASE_DIR/wav; - try_files $uri $uri/ =404; - } - location /fic { - add_header Cache-Control 'must-revalidate, proxy-revalidate'; - alias $SOUNDBASE_DIR/fic; - try_files $uri $uri/ =404; - } - location /prg { - auth_basic "Entrez votre identifiant et mot de passe"; - auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; - alias $SOUNDBASE_DIR/prg; - try_files $uri $uri/ =404; - } - location /lst { - auth_basic "Entrez votre identifiant et mot de passe"; - auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; - alias $SOUNDBASE_DIR/lst; - try_files $uri $uri/ =404; - } # Admin interface location /manager { - alias $HTTP_DIR/manager/dist; - auth_basic "Entrez votre identifiant et mot de passe"; - auth_basic_user_file $SOUNDBASE_DIR/users.htpasswd; + alias $DATA_DIR/soundbase/manager; try_files $uri $uri/ =404; } } diff --git a/services/soundbase.radiokipik.org/regen_website.sh b/services/soundbase.radiokipik.org/regen_website.sh new file mode 100755 index 0000000..830eea5 --- /dev/null +++ b/services/soundbase.radiokipik.org/regen_website.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -euo pipefail + + + +echo "Generate website" +if [ -e "$DATA_DIR/soundbase/fic/_website-_config.fic" ] ; then + "omarustwebsite-$OMA_DOCKER_VERSION" --soundbase-path $DATA_DIR/soundbase --output $DATA_DIR/soundbase/website/ --soundbase-prefix '/soundbase' --website-prefix '' --manager-url "https://$JC_SERVICE/manager" --player-url '/soundbase/player' --websocket-port "$WEBSOCKET_PORT" --radio-host "$RADIO_HOST" +fi + +echo "(kill and) start lsyncd with head" +killall lsyncd 2>/dev/null || true +cat "$DOCKER_DIR/lsyncd.conf" | template.sh "$DOCKER_DIR/.env" > "$TMP_DIR/lsyncd.conf" +lsyncd "$TMP_DIR/lsyncd.conf" 2>&1 >> "$TMP_DIR/lsyncd.log" & diff --git a/services/soundbase.radionimaitre.oma-radio.fr/.env b/services/soundbase.radionimaitre.oma-radio.fr/.env new file mode 100644 index 0000000..1c5b64a --- /dev/null +++ b/services/soundbase.radionimaitre.oma-radio.fr/.env @@ -0,0 +1,19 @@ +TZ=Europe/Paris +OMA_DOCKER_VERSION=dev +WEBSOCKET_PORT=2003 +TELECOM_SERVER_PORT=3493 +MUX_SERVER_PORT=9003 +RADIO_NAME_SIMPLE=radionimaitre +OMA_CONFIG_NomRadio=radionimaitre +RADIO_NAME_PRETTY="radionimaitre Radio" +RADIO_HOST=radionimaitre.oma-radio.fr +COMPOSE_NAME=radionimaitreoma-radiofr +DOCKER_INSTANCES_PREFIX=radionimaitreoma-radiofr- +DOCKER_INSTANCES_SUFIX=-1 +DATA_DIR=/data/radionimaitre.oma-radio.fr +USE_SSL=true +PUBLIC_WEBSITE_UPSTREAM=https://static.oma-radio.fr/player-interface/1.3.0 +MANAGER_WEBSITE_UPSTREAM=https://static.oma-radio.fr/single-manager/1.1.0 +SYNCTHINGS_API_KEY=425qLiE5QMJmFjgoxUHRgxD2icWNmkdy +SYNCTHINGS_LABEL_PREFIX="[oma] [radionimaitre] " +SYNCTHINGS_PRIVATE_KEY="/keys/Niilos" diff --git a/services/soundbase.radionimaitre.oma-radio.fr/docker-compose.yml b/services/soundbase.radionimaitre.oma-radio.fr/docker-compose.yml new file mode 120000 index 0000000..443cc57 --- /dev/null +++ b/services/soundbase.radionimaitre.oma-radio.fr/docker-compose.yml @@ -0,0 +1 @@ +../soundbase/docker-compose.yml \ No newline at end of file diff --git a/services/soundbase.radionimaitre.oma-radio.fr/nginx_server.conf b/services/soundbase.radionimaitre.oma-radio.fr/nginx_server.conf new file mode 120000 index 0000000..5b1b163 --- /dev/null +++ b/services/soundbase.radionimaitre.oma-radio.fr/nginx_server.conf @@ -0,0 +1 @@ +../soundbase/nginx_server.conf \ No newline at end of file diff --git a/services/soundbase/docker-compose.yml b/services/soundbase/docker-compose.yml new file mode 100644 index 0000000..2cc020b --- /dev/null +++ b/services/soundbase/docker-compose.yml @@ -0,0 +1,137 @@ +version: '3' +services: + anthracite_jukebox: + image: registry.gitlab.com/omaradio/core/oma-jukebox:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_CONFIG_TelecommandeHost: $RADIO_HOST + OMA_CONFIG_TelecommandePort: $TELECOM_SERVER_PORT + OMA_CONFIG_Client1Host: mux.radiodemo.oma-radio.fr + OMA_CONFIG_Client1Port: $MUX_SERVER_PORT + volumes: + - $DATA_DIR:/app/soundBase + - $DATA_DIR/secours-jingle.wavM:/app/secours/secours-jingle.wavM + restart: unless-stopped + networks: + default: + ipv4_address: $NET.102 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M + + azurite_jukebox_simulator: + image: registry.gitlab.com/omaradio/core/oma-jukebox-simulator:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_CONFIG_TelecommandeHost: $RADIO_HOST + volumes: + - $DATA_DIR:/app/soundBase + restart: unless-stopped + networks: + default: + ipv4_address: $NET.103 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M + + # aventurine_transcode: + # image: jeancloud/transcode:$OMA_DOCKER_VERSION + # env_file: .env + # restart: unless-stopped + + + agate_importer: + image: registry.gitlab.com/omaradio/core/oma-baseimport:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_CONFIG_TelecommandeHost: $RADIO_HOST + volumes: + - $DATA_DIR:/app/soundBase + restart: unless-stopped + networks: + default: + ipv4_address: $NET.104 + deploy: + resources: + limits: + cpus: '0.50' + memory: 500M + + + rubis_base_mg: + image: registry.gitlab.com/omaradio/core/oma-base-mg:$OMA_DOCKER_VERSION + env_file: .env + environment: + OMA_CONFIG_TelecommandeHost: $RADIO_HOST + restart: unless-stopped + volumes: + - $DATA_DIR:/soundbase + networks: + default: + ipv4_address: $NET.106 + deploy: + resources: + limits: + cpus: '0.50' + memory: 100M + + + system_api: + image: jeancloud/system-api:dev + env_file: .env + environment: + OMA_CONFIG_TelecommandeHost: $RADIO_HOST + UID: 33 + SOUNDBASE_PATH: /soundbase + MOUNT: /api + CONFIG_PATH: /config + restart: unless-stopped + volumes: + - /tmp/uwsgi/$JC_SERVICE:/tmp/uwsgi + - /var/run/docker.sock:/var/run/docker.sock + - $DATA_DIR:/soundbase + networks: + default: + ipv4_address: $NET.107 + deploy: + resources: + limits: + cpus: '0.50' + memory: 500M + + + #ammolite_mp3_addon: + # image: jeancloud/mp3addon:$OMA_DOCKER_VERSION + # env_file: .env + # environment: + # OMA_CONFIG_TelecommandeHost: $NET.101 + # OMA_CONFIG_PigePrefix: /opt + # restart: unless-stopped + # volumes: + # - $DATA_DIR:/app/soundbase + # networks: + # default: + # ipv4_address: $NET.109 + # deploy: + # resources: + # limits: + # cpus: '0.05' + + # doxy: + # image: qnib/doxy + # volumes: + # - /tmp/radiodemo.oma-radio.fr/doxy:/tmp/doxy + # - /data/radiodemo.oma-radio.fr/doxy.pattern:/etc/doxy.pattern + # - /var/run/docker.sock:/var/run/docker.sock + # environment: + # DOXY_PROXY_SOCKET: /tmp/doxy/doxy.sock + +networks: + default: + ipam: + config: + - subnet: $NET.0/24 diff --git a/services/soundbase/nginx_server.conf b/services/soundbase/nginx_server.conf new file mode 100644 index 0000000..ab38c29 --- /dev/null +++ b/services/soundbase/nginx_server.conf @@ -0,0 +1,121 @@ +# Parameters: +# radio name +# file path +# ws port (local) +# wss port (open) +# upload service port +# ssl certs location + +# TODO +# /speedtest-down returns random data +# can use : openssl enc -aes-256-ctr -pass pass:"$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64)" -nosalt < /dev/zero > randomfile.bin +# /speedtest-up just eat everything it can + + + + + +server { + listen 80; + listen [::]:80; + server_name $JC_SERVICE; + + root $DATA_DIR; + index index.html; + + location ~ /api(/.*) { + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $DATA_DIR/users.htpasswd; + 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'; + if_modified_since off; + expires off; + etag off; + } + + location /pige{ + alias $DATA_DIR/pige; + try_files $uri $uri/ =404; + } + location /png { + alias $DATA_DIR/png; + try_files $uri $uri/ =404; + } + location /webpL { + alias $DATA_DIR/webpL; + try_files $uri $uri/ =404; + } + location /webpH { + alias $DATA_DIR/webpH; + try_files $uri $uri/ =404; + } + location /ogg { + alias $DATA_DIR/ogg; + try_files $uri $uri/ =404; + } + location /txt { + alias $DATA_DIR/txt; + try_files $uri $uri/ =404; + } + location /wavM { + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $DATA_DIR/users.htpasswd; + alias $DATA_DIR/wavM; + try_files $uri $uri/ =404; + } + location /import { + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $DATA_DIR/users.htpasswd; + alias $DATA_DIR/import; + try_files $uri $uri/ =404; + } + location /export { + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $DATA_DIR/users.htpasswd; + alias $DATA_DIR/export; + try_files $uri $uri/ =404; + } + location /wav { + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $DATA_DIR/users.htpasswd; + alias $DATA_DIR/wav; + try_files $uri $uri/ =404; + } + location /fic { + alias $DATA_DIR/fic; + try_files $uri $uri/ =404; + } + location /prg { + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $DATA_DIR/users.htpasswd; + alias $DATA_DIR/prg; + try_files $uri $uri/ =404; + } + location /lst { + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $DATA_DIR/users.htpasswd; + alias $DATA_DIR/lst; + try_files $uri $uri/ =404; + } + location /statique { + alias $DATA_DIR/statique; + try_files $uri $uri/ =404; + } + + # Admin interface + location /manager { + auth_basic "Entrez votre identifiant et mot de passe"; + auth_basic_user_file $DATA_DIR/users.htpasswd; + try_files $uri $uri/ =404; + } +} diff --git a/services/studios.oma-radio.fr/wg-omastudios.sh b/services/studios.oma-radio.fr/wg-omastudios.sh new file mode 100755 index 0000000..a09ed7b --- /dev/null +++ b/services/studios.oma-radio.fr/wg-omastudios.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +set -euo pipefail + +if [ ! -e "$DATA_DIR/privkey" ] ; then + wg genkey | tee "$DATA_DIR/privkey" | wg pubkey > "$DATA_DIR/pubkey" +fi + +. .env +filename="$(basename "$0")" +ifname="${filename:3:-3}" + +echo " +[Interface] +PrivateKey = $(cat $DATA_DIR/privkey) +ListenPort = 51113 +Address = 10.100.254.254/32 + +[Peer] # adrian +PublicKey = 14yKNmSfD2lrWU+d/RJBPNvh9pZ/nW4bK27F9nTgvk0= +AllowedIPs = 10.100.254.253/32 + +[Peer] # Nico +PublicKey = jsXBs8tZn1sWT73xx3DWEdGAWv6SjfQ2TAxX+8pL6mU= +AllowedIPs = 10.100.254.252/32 + +[Peer] # Vmassat +PublicKey = D1v9f2nkvn4UGg3TMfbhsqY0HRFIJ5+lHrtn2l258Sk= +AllowedIPs = 10.100.4.13/32 + +" diff --git a/services/valisekipik.studios.oma-radio.fr/wgns-valisekipik.sh b/services/valisekipik.studios.oma-radio.fr/wgns-valisekipik.sh new file mode 100755 index 0000000..53a396e --- /dev/null +++ b/services/valisekipik.studios.oma-radio.fr/wgns-valisekipik.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +set -euo pipefail + +. .env + +wgif="$1" +net="10.100.1" +privfile="$DATA_DIR/wgif.wgprivatekey" + +# Create key if doesnt exists +if [ ! -e "$privfile" ] ; then + touch "$privfile" + chmod 700 "$privfile" + wg genkey > "$privfile" +fi + +# Print wg-quick config +echo " +[Interface] +PrivateKey = $(cat "$privfile") +ListenPort = $((51800+$JC_ID)) +Address = $net.254/32 + +[Peer] # Adrian +PublicKey = 14yKNmSfD2lrWU+d/RJBPNvh9pZ/nW4bK27F9nTgvk0= +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 +"