diff options
Diffstat (limited to 'roles')
50 files changed, 850 insertions, 909 deletions
diff --git a/roles/bbb/README.md b/roles/bbb/README.md new file mode 100644 index 0000000..225dd44 --- /dev/null +++ b/roles/bbb/README.md @@ -0,0 +1,38 @@ +Role Name +========= + +A brief description of the role goes here. + +Requirements +------------ + +Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. + +Role Variables +-------------- + +A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. + +Dependencies +------------ + +A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. + +Example Playbook +---------------- + +Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: + + - hosts: servers + roles: + - { role: username.rolename, x: 42 } + +License +------- + +BSD + +Author Information +------------------ + +An optional section for the role authors to include contact information, or a website (HTML is not allowed). diff --git a/roles/bbb/defaults/main.yml b/roles/bbb/defaults/main.yml new file mode 100644 index 0000000..17c44b0 --- /dev/null +++ b/roles/bbb/defaults/main.yml @@ -0,0 +1,4 @@ +bbb_docker_repo_dir: /data/emacsconf/shared/bbb-docker-repo +bbb_docker_dir: /data/emacsconf/shared/bbb-docker +bbb_domain: bbb.emacsverse.org +bbb_ip: 207.66.177.26 diff --git a/roles/bbb/handlers/main.yml b/roles/bbb/handlers/main.yml new file mode 100644 index 0000000..40aff70 --- /dev/null +++ b/roles/bbb/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for bbb diff --git a/roles/bbb/meta/main.yml b/roles/bbb/meta/main.yml new file mode 100644 index 0000000..c572acc --- /dev/null +++ b/roles/bbb/meta/main.yml @@ -0,0 +1,52 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.1 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. diff --git a/roles/bbb/tasks/main.yml b/roles/bbb/tasks/main.yml new file mode 100644 index 0000000..1a4b115 --- /dev/null +++ b/roles/bbb/tasks/main.yml @@ -0,0 +1,18 @@ +--- +- name: Create group + group: + name: "{{ emacsconf_group }}" + state: present +- name: Create user + user: + name: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + state: present +- name: Add public key for authorized access + ansible.posix.authorized_key: + user: "{{ emacsconf_user }}" + state: present + key: '{{ item }}' + with_file: + - ../../base/files/keys/sachac + - ../../base/files/keys/orga diff --git a/roles/bbb/templates/env.template b/roles/bbb/templates/env.template new file mode 100644 index 0000000..65e8770 --- /dev/null +++ b/roles/bbb/templates/env.template @@ -0,0 +1,202 @@ +# ==================================== +# ADDITIONS to BigBlueButton +# ==================================== +# (place a '#' before to disable them) + +# HTTPS Proxy +# fully automated Lets Encrypt certificates +ENABLE_HTTPS_PROXY=true +# If your network doesn't allow access to DNS at 8.8.8.8 specify your own resolvers +#RESOLVER_ADDRESS=x.x.x.x + +# coturn (a TURN Server) +# requires either the abhove HTTPS Proxy to be enabled +# or TLS certificates to be mounted to container +ENABLE_COTURN=true +#COTURN_TLS_CERT_PATH= +#COTURN_TLS_KEY_PATH= + +# Greenlight Frontend +# https://docs.bigbluebutton.org/greenlight/gl-overview.html +ENABLE_GREENLIGHT=true + +# Enable Webhooks +# used by some integrations +#ENABLE_WEBHOOKS=true + +# Prometheus Exporter +# serves the bigbluebutton-exporter under following URL: +# https://yourdomain/bbb-exporter +#ENABLE_PROMETHEUS_EXPORTER=true +#ENABLE_PROMETHEUS_EXPORTER_OPTIMIZATION=true + +# Recording +# IMPORTANT: this is currently a big privacy issues, because it will +# record everything which happens in the conference, even when the button +# suggets, that it does not. +# https://github.com/bigbluebutton/bigbluebutton/issues/9202 +# make sure that you get peoples consent, before they join a room +ENABLE_RECORDING=true +#REMOVE_OLD_RECORDING=false +#RECORDING_MAX_AGE_DAYS=14 + +# ==================================== +# SECRETS +# ==================================== +# important! change these to any random values +SHARED_SECRET={{ bbb_shared_secret }} +ETHERPAD_API_KEY={{ bbb_etherpad_api_key }} +RAILS_SECRET={{ bbb_rails_secret }} +POSTGRESQL_SECRET={{ bbb_postgresql_secret }} +FSESL_PASSWORD={{ bbb_fsesl_password }} + + + +# ==================================== +# CONNECTION +# ==================================== + +DOMAIN={{ bbb_domain }} + +EXTERNAL_IPv4={{ bbb_ip }} +EXTERNAL_IPv6= + +# STUN SERVER +# stun.freeswitch.org +STUN_IP={{ bbb_ip }} +STUN_PORT=3478 + +# TURN SERVER +# uncomment and adjust following two lines to add an external TURN server +TURN_SERVER=turns:{{ bbb_domain }}:5349?transport=tcp +TURN_SECRET={{ bbb_turn_secret }} + +# Allowed SIP IPs +# due to high traffic caused by bots, by default the SIP port is blocked. +# but you can allow access by your providers IP or IP ranges (comma seperated) +# Hint: if you want to allow requests from every IP, you can use 0.0.0.0/0 +SIP_IP_ALLOWLIST= + + +# ==================================== +# CUSTOMIZATION +# ==================================== + +CLIENT_TITLE=BigBlueButton + +# use following lines to replace the default welcome message and footer +WELCOME_MESSAGE="Welcome to <b>%%CONFNAME%%</b>!<br><br>For help on using BigBlueButton see these (short) <a href='https://www.bigbluebutton.org/html5' target='_blank'><u>tutorial videos</u></a>.<br><br>To join the audio bridge click the speaker button. Use a headset to avoid causing background noise for others." +WELCOME_FOOTER="This server is running <a href='https://docs.bigbluebutton.org/'' target='_blank'><u>BigBlueButton</u></a>." + +# use following line for an additional SIP dial-in message +#WELCOME_FOOTER="This server is running <a href='https://docs.bigbluebutton.org/' target='_blank'><u>BigBlueButton</u></a>. <br><br>To join this meeting by phone, dial:<br> INSERT_YOUR_PHONE_NUMBER_HERE<br>Then enter %%CONFNUM%% as the conference PIN number." + +# for a different default presentation, place the pdf file in ./conf/ and +# adjust the following path +DEFAULT_PRESENTATION=./mod/nginx/default.pdf + +# language of sound announcements +# options: +# - en-ca-june - EN Canadian June +# - en-us-allison - US English Allison +# - en-us-callie - US English Callie (default) +# - de-de-daedalus3 - German by Daedalus3 (https://github.com/Daedalus3/freeswitch-german-soundfiles) +# - es-ar-mario - Spanish/Argentina Mario +# - fr-ca-june - FR Canadian June +# - pt-br-karina - Brazilian Portuguese Karina +# - ru-RU-elena - RU Russian Elena +# - ru-RU-kirill - RU Russian Kirill +# - ru-RU-vika - RU Russian Viktoriya +# - sv-se-jakob - Swedish (Sweden) Jakob +# - zh-cn-sinmei - Chinese/China Sinmei +# - zh-hk-sinmei - Chinese/Hong Kong Sinmei +SOUNDS_LANGUAGE=en-us-callie + +# set to false to disable listenOnlyMode +LISTEN_ONLY_MODE=true + +# set to true to disable echo test +DISABLE_ECHO_TEST=false + +# set to true to automatically share webcam +AUTO_SHARE_WEBCAM=false + +# set to true to disable video preview for webcam sharing +DISABLE_VIDEO_PREVIEW=false + +# set to false to disable chat +CHAT_ENABLED=true + +# set to true to start chat closed +CHAT_START_CLOSED=false + +# set to true to disable announcements "You are now (un-)muted" +DISABLE_SOUND_MUTED=false + +# set to true to disable announcement "You are the only person in this conference" +DISABLE_SOUND_ALONE=false + +# maximum count of breakout rooms per meeting +# Warning: increasing the limit of breakout rooms per meeting +# can generate excessive overhead to the server. We recommend +# this value to be kept under 12. +BREAKOUTROOM_LIMIT=8 + +# set to false to disable the learning dashboard +ENABLE_LEARNING_DASHBOARD=true + +# ==================================== +# Tuning +# ==================================== +# Default = 2; Min = 1; Max = 4 +# On powerful systems with high number of meetings you can set values up to 4 to accelerate handling of events +NUMBER_OF_BACKEND_NODEJS_PROCESSES=2 + +# Default = 2; Min = 1; Max = 8 +# Set a number between 1 and 4 times the value of NUMBER_OF_BACKEND_NODEJS_PROCESSES where higher number helps with meetings +# stretching the recommended number of users in BigBlueButton +NUMBER_OF_FRONTEND_NODEJS_PROCESSES=2 + + +# ==================================== +# GREENLIGHT CONFIGURATION +# ==================================== + +### SMTP CONFIGURATION +# Emails are required for the basic features of Greenlight to function. +# Please refer to your SMTP provider to get the values for the variables below +#SMTP_SENDER_EMAIL= +#SMTP_SENDER_NAME= +#SMTP_SERVER= +#SMTP_PORT= +#SMTP_DOMAIN=bbb.emacsverse.org +#SMTP_USERNAME= +#SMTP_PASSWORD= +#SMTP_AUTH= +#SMTP_STARTTLS_AUTO=true +#SMTP_STARTTLS=false +#SMTP_TLS=false +#SMTP_SSL_VERIFY=true + +### EXTERNAL AUTHENTICATION METHODS +# +#OPENID_CONNECT_CLIENT_ID= +#OPENID_CONNECT_CLIENT_SECRET= +#OPENID_CONNECT_ISSUER= +#OPENID_CONNECT_REDIRECT= + +# To enable hCaptcha on the user sign up and sign in, define these 2 keys +#HCAPTCHA_SITE_KEY= +#HCAPTCHA_SECRET_KEY= + +# Set these if you are using a Simple Storage Service (S3) +# Uncomment S3_ENDPOINT only if you are using a S3 OTHER than Amazon Web Service (AWS) S3. +#S3_ACCESS_KEY_ID= +#S3_SECRET_ACCESS_KEY= +#S3_REGION= +#S3_BUCKET= +#S3_ENDPOINT= + +# Define the default locale language code (i.e. 'en' for English) from the fallowing list: +# [en, ar, fr, es] +#DEFAULT_LOCALE=en diff --git a/roles/bbb/tests/inventory b/roles/bbb/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/roles/bbb/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/roles/bbb/tests/test.yml b/roles/bbb/tests/test.yml new file mode 100644 index 0000000..72d74f0 --- /dev/null +++ b/roles/bbb/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - bbb diff --git a/roles/bbb/vars/main.yml b/roles/bbb/vars/main.yml new file mode 100644 index 0000000..de701b8 --- /dev/null +++ b/roles/bbb/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for bbb diff --git a/roles/caption/tasks/main.yml b/roles/caption/tasks/main.yml index d3ee4c0..96b3198 100644 --- a/roles/caption/tasks/main.yml +++ b/roles/caption/tasks/main.yml @@ -6,17 +6,20 @@ - cmake - jq - inotify-tools + - pipx - name: Install whisper - ansible.builtin.pip: + community.general.pipx: name: git+https://github.com/openai/whisper.git - name: Install Python packages - ansible.builtin.pip: - name: - - lhotse - - webvtt-py - - tqdm - - torchaudio - - num2words + community.general.pipx: + name: "{{ item }}" + install_deps: true + loop: + - lhotse + - webvtt-py + - tqdm + - torchaudio + - num2words - name: Set up aeneas include_tasks: aeneas.yml - name: Create group diff --git a/roles/caption/templates/process-captions.py b/roles/caption/templates/process-captions.py index fde766c..bdbfa1e 100755 --- a/roles/caption/templates/process-captions.py +++ b/roles/caption/templates/process-captions.py @@ -40,7 +40,7 @@ import json import torch THREADS = {{ cpus }} -VIDEO_REGEXP = '\\.(webm|mov|mp4|mkv)$' +VIDEO_REGEXP = '\\.(webm|mov|mp4|mkv|mpv)$' AUDIO_REGEXP = '\\.(ogg|opus)$' ALWAYS = False TRIM_AUDIO = False diff --git a/roles/edit/templates/emacsconf-edit.el b/roles/edit/templates/emacsconf-edit.el index 65e15b7..603d0a3 100644 --- a/roles/edit/templates/emacsconf-edit.el +++ b/roles/edit/templates/emacsconf-edit.el @@ -85,6 +85,8 @@ (find-file "{{ emacsconf_private_dir }}/conf.org") (setq emacsconf-cache-dir "{{ emacsconf_caption_dir }}/cache") +(setq case-fold-search t) (emacsconf-add-org-after-todo-state-change-hook) +(setq emacsconf-publishing-phase 'conference) (unless noninteractive (emacsconf-erc-connect)) (setq tab-width 2) diff --git a/roles/live/tasks/main.yml b/roles/live/tasks/main.yml index cb0029a..8ff5903 100644 --- a/roles/live/tasks/main.yml +++ b/roles/live/tasks/main.yml @@ -7,3 +7,11 @@ loop: - "{{ emacsconf_year }}" - "{{ emacsconf_year }}/watch" +- name: Set up nginx.conf + template: + src: live.emacsconf.org.conf + dest: /etc/nginx/sites-available/live.emacsconf.org +- name: Reload nginx + service: + name: nginx + state: reloaded diff --git a/roles/media/tasks/main.yml b/roles/media/tasks/main.yml index 8cd854d..e9daaef 100644 --- a/roles/media/tasks/main.yml +++ b/roles/media/tasks/main.yml @@ -11,6 +11,10 @@ file: path: /var/www/{{ media_server_name }}/{{ emacsconf_year }}/backstage state: directory +- name: Ensure current directory exists + file: + path: /var/www/{{ media_server_name }}/{{ emacsconf_year }}/current + state: directory - name: Create group group: name: "{{ emacsconf_group }}" @@ -68,3 +72,48 @@ service: name: nginx state: reloaded +- name: Symlink the current year's backstage directory + file: + src: /var/www/{{ media_server_name }}/{{ emacsconf_year }}/backstage + dest: "~{{ emacsconf_user }}/backstage" + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + state: link +- name: Symlink the current year's directory + file: + src: /var/www/{{ media_server_name }}/{{ emacsconf_year }} + dest: "~{{ emacsconf_user }}/{{ emacsconf_year }}" + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + state: link +- name: Symlink the current year's directory as current + file: + src: /var/www/{{ media_server_name }}/{{ emacsconf_year }} + dest: "~{{ emacsconf_user }}/current" + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + state: link +- name: Create the bin directory + tags: media-scripts + file: + state: directory + path: "~{{ emacsconf_user }}/bin" + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" +- name: Add the bin directory to the path + tags: media-scripts + lineinfile: + dest: "~{{ emacsconf_user }}/.bashrc" + state: present + line: "export PATH=$PATH:~/bin" +- name: Create batch scripts + tags: media-scripts + template: + src: "{{ item }}" + dest: "~{{ emacsconf_user }}/bin/{{ item }}" + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + mode: 0755 + loop: + - bbb-open + - bbb-before diff --git a/roles/media/templates/nginx-include b/roles/media/templates/nginx-include index f80ed76..4d1eabe 100644 --- a/roles/media/templates/nginx-include +++ b/roles/media/templates/nginx-include @@ -12,15 +12,30 @@ location /{{ emacsconf_year }}/backstage { expires off; etag off; } + location ~* \.vtt$ { + add_header Cache-Control "no-cache, no-store, must-revalidate"; + add_header Pragma "no-cache"; + add_header Expires "0"; + } + location /{{ emacsconf_year }}/{{ emacsconf_id }}.ics { - auth_basic off; - } + auth_basic off; + add_header Cache-Control "no-cache, no-store, must-revalidate"; + add_header Pragma "no-cache"; + add_header Expires "0"; +} location /{{ emacsconf_year }}/schedules/ { auth_basic off; + add_header Cache-Control "no-cache, no-store, must-revalidate"; + add_header Pragma "no-cache"; + add_header Expires "0"; } {% for track in emacsconf_tracks %} location /{{ emacsconf_year }}/{{ emacsconf_id }}-{{ track.id }}.ics { auth_basic off; + add_header Cache-Control "no-cache, no-store, must-revalidate"; + add_header Pragma "no-cache"; + add_header Expires "0"; } {% endfor %} {% if media_protect_root %} diff --git a/roles/media/templates/nginx-site-config b/roles/media/templates/nginx-site-config index 4dbdaaa..ba25cba 100644 --- a/roles/media/templates/nginx-site-config +++ b/roles/media/templates/nginx-site-config @@ -2,4 +2,9 @@ server { listen 80; server_name {{ media_server_name }}; root /var/www/{{ media_server_name }}; -}
\ No newline at end of file + location ~* \.vtt$ { + add_header Cache-Control "no-cache, no-store, must-revalidate"; + add_header Pragma "no-cache"; + add_header Expires "0"; + } +} diff --git a/roles/obs/defaults/main.yml b/roles/obs/defaults/main.yml index 1c193e0..d95b900 100644 --- a/roles/obs/defaults/main.yml +++ b/roles/obs/defaults/main.yml @@ -3,7 +3,7 @@ ff_vcustom: rt cpu-used=5 threads=2 error-resilient=1 crf=30 g=120 minrate=1.5M ff_vbitrate: 1500 ff_vgopsize: 120 obs_profile_path: /home/{{ emacsconf_user }}/.config/obs-studio/basic/profiles -emacsconf_asset_dir: /data/{{ emacsconf_id }}/assets +emacsconf_asset_dir: /data/{{ emacsconf_id }}/shared/{{ emacsconf_year }}/assets mumble_server: mumble.emacsconf.org background_music_dir: "{{ emacsconf_asset_dir }}/music" background_music_volume: 30 diff --git a/roles/obs/tasks/track.yml b/roles/obs/tasks/track.yml index 3d3a8d6..cbd4b39 100644 --- a/roles/obs/tasks/track.yml +++ b/roles/obs/tasks/track.yml @@ -103,7 +103,7 @@ include_tasks: emacs.yml - name: Set up symbolic links file: - src: "/data/{{ emacsconf_id }}/assets/stream" + src: "/data/{{ emacsconf_id }}/shared/{{ emacsconf_year }}/assets/stream" dest: "~{{ emacsconf_user }}/stream" state: link diff --git a/roles/obs/templates/emacsconf-stream-config.el b/roles/obs/templates/emacsconf-stream-config.el index bd5ffd7..2aa886b 100644 --- a/roles/obs/templates/emacsconf-stream-config.el +++ b/roles/obs/templates/emacsconf-stream-config.el @@ -13,7 +13,9 @@ (setq emacsconf-stream-track "{{ item.name }}") (autoload 'text-property-search-forward "text-property-search") (add-to-list 'load-path "~/emacsconf-el") +(setq tab-width 2) +(setq case-fold-search t) +(setq emacsconf-cache-dir "{{ emacsconf_caption_dir }}/cache") (require 'emacsconf) (require 'emacsconf-stream) (emacsconf-stream-display-clock-and-countdown) -(setq tab-width 2) diff --git a/roles/obs/templates/i3-config b/roles/obs/templates/i3-config index 1787b64..31a7b40 100644 --- a/roles/obs/templates/i3-config +++ b/roles/obs/templates/i3-config @@ -23,7 +23,7 @@ font pango:monospace 8 # xss-lock grabs a logind suspend inhibit lock and will use i3lock to lock the # screen before suspend. Use loginctl lock-session to lock your screen. -exec --no-startup-id xss-lock --transfer-sleep-lock -- i3lock --nofork +# exec --no-startup-id xss-lock --transfer-sleep-lock -- i3lock --nofork # NetworkManager is the most popular way to manage wireless networks on Linux, # and nm-applet is a desktop environment-independent system tray GUI for it. diff --git a/roles/obs/templates/intro b/roles/obs/templates/intro index bf02dc3..7af9c4c 100755 --- a/roles/obs/templates/intro +++ b/roles/obs/templates/intro @@ -8,7 +8,7 @@ fi SLUG=$1 FILE=$1 if [[ ! -f $FILE ]]; then - LIST=({{ emacsconf_caption_dir }}/assets/stream/emacsconf-{{ emacsconf_year }}-$FILE--*.webm) + LIST=({{ emacsconf_caption_dir }}/cache/emacsconf-{{ emacsconf_year }}-$FILE--*.webm) FILE="${LIST[0]}" BY_SLUG=1 else @@ -16,8 +16,8 @@ else fi shift overlay $SLUG -if [[ -f {{ emacsconf_caption_dir }}/assets/intros/$SLUG.webm ]]; then - mpv {{ emacsconf_caption_dir }}/assets/intros/$SLUG.webm +if [[ -f "$FILE" ]]; then + mpv "$FILE" else firefox {{ emacsconf_caption_dir }}/assets/in-between/$SLUG.png fi diff --git a/roles/obs/templates/music b/roles/obs/templates/music index 3e729ec..a5a6a31 100755 --- a/roles/obs/templates/music +++ b/roles/obs/templates/music @@ -1,5 +1,5 @@ if screen -list | grep -q background; then echo "Already running in screen, attach with screen -x background" else - screen -dmS background /bin/bash -c "mpv {{ background_music_dir }}/* --shuffle --loop=inf --volume={{ background_music_volume }}" + screen -dmS background /bin/bash -c "mpv {{ background_music_dir }}/* --shuffle --loop-playlist=inf --volume={{ background_music_volume }}" fi diff --git a/roles/obs/templates/overlay b/roles/obs/templates/overlay index 1361884..0836a59 100755 --- a/roles/obs/templates/overlay +++ b/roles/obs/templates/overlay @@ -3,20 +3,20 @@ SLUG=$(echo "$1" | perl -ne 'if (/emacsconf-[0-9]*-(.*?)--/) { print $1; } else { print; }') -if [[ -f {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-other.svg.png ]]; then +if [[ -f {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-other.png ]]; then echo "Found other overlay for $SLUG, copying" - cp {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-other.svg.png ~/other.png -elif [[ -f {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.svg.png ]]; then + cp {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-other.png ~/other.png +elif [[ -f {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.png ]]; then echo "Found video overlay for $SLUG, copying" - cp {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.svg.png ~/other.png + cp {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.png ~/other.png else - echo "Could not find {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-other.svg.png, please override ~/other.png manually" - cp {{ emacsconf_caption_dir }}/assets/overlays/blank-other.svg.png ~/other.png + echo "Could not find {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-other.png, please override ~/other.png manually" + cp {{ emacsconf_caption_dir }}/assets/overlays/blank-other.png ~/other.png fi -if [[ -f {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.svg.png ]]; then +if [[ -f {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.png ]]; then echo "Found video overlay for $SLUG, copying" - cp {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.svg.png ~/video.png + cp {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.png ~/video.png else - echo "Could not find {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.svg.png, override ~/video.png manually" - cp {{ emacsconf_caption_dir }}/assets/overlays/blank-video.svg.png ~/video.png + echo "Could not find {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.png, override ~/video.png manually" + cp {{ emacsconf_caption_dir }}/assets/overlays/blank-video.png ~/video.png fi diff --git a/roles/obs/templates/play b/roles/obs/templates/play index 22f58c7..69632d4 100755 --- a/roles/obs/templates/play +++ b/roles/obs/templates/play @@ -11,18 +11,25 @@ CACHE_DIR="{{ emacsconf_caption_dir }}/cache" FIREFOX_NAME=firefox-esr SLUG=$1 PREFIX=$(get-file-prefix $SLUG) - +PREFER_LIVE=$(jq -r ".talks[] | select(.slug == \"$SLUG\") | .\"prefer-live\" " < "$BASE_DIR/talks.json") /usr/local/bin/reset-state # Update the overlay overlay $SLUG +if [ "$PREFER_LIVE" = "t" ]; then + /usr/local/bin/bbb $SLUG + exit 0 +fi + # Play the video if it exists. If it doesn't exist, switch to the BBB room and stop processing. if [ "x$TEST_MODE" = "x" ]; then - LIST=($BASE_DIR/assets/stream/{{ emacsconf_id }}-{{ emacsconf_year }}-$SLUG*--main.webm) + LIST=($CACHE_DIR/{{ emacsconf_id }}-{{ emacsconf_year }}-$SLUG*--main.webm) else LIST=($BASE_DIR/assets/test/{{ emacsconf_id }}-{{ emacsconf_year }}-$SLUG*--main.webm) fi + + FILE="${LIST[0]}" # No file in the stream directory; check for original files in the stream directory, then check the cache NOSUB="" diff --git a/roles/obs/templates/play-with-intro b/roles/obs/templates/play-with-intro index 7f7865b..0390f8f 100755 --- a/roles/obs/templates/play-with-intro +++ b/roles/obs/templates/play-with-intro @@ -13,15 +13,10 @@ PREFIX=$(get-file-prefix $SLUG) /usr/local/bin/reset-state # Update the overlay -overlay $SLUG +/usr/local/bin/overlay $SLUG # Play the intro if it exists. If it doesn't exist, switch to the intro slide and stop processing. -if [[ -f $CACHE_DIR/$PREFIX--intro.webm ]]; then - mpv $CACHE_DIR/$PREFIX--intro.webm -else - firefox --kiosk $BASE_DIR/assets/in-between/$SLUG.png - exit 0 -fi +/usr/local/bin/intro $SLUG /usr/local/bin/play $SLUG diff --git a/roles/obs/templates/set-overlay b/roles/obs/templates/set-overlay index 0b6712b..8a408bf 100644 --- a/roles/obs/templates/set-overlay +++ b/roles/obs/templates/set-overlay @@ -6,20 +6,20 @@ if [[ ! -f $FILE ]]; then fi shift SLUG=$(echo "$FILE" | perl -ne 'if (/^emacsconf-[0-9]*-(.*?)--/) { print $1; } else { print; }') -if [[ -f {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-other.svg.png ]]; then +if [[ -f {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-other.png ]]; then echo "Found other overlay for $SLUG, copying" - cp {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-other.svg.png ~/other.png -elif [[ -f {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.svg.png ]]; then + cp {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-other.png ~/other.png +elif [[ -f {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.png ]]; then echo "Found video overlay for $SLUG, copying" - cp {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.svg.png ~/other.png + cp {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.png ~/other.png else - echo "Could not find {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-other.svg.png, please override ~/other.png manually" - cp {{ emacsconf_caption_dir }}/assets/overlays/blank-other.svg.png ~/other.png + echo "Could not find {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-other.png, please override ~/other.png manually" + cp {{ emacsconf_caption_dir }}/assets/overlays/blank-other.png ~/other.png fi -if [[ -f {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.svg.png ]]; then +if [[ -f {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.png ]]; then echo "Found video overlay for $SLUG, copying" - cp {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.svg.png ~/video.png + cp {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.png ~/video.png else - echo "Could not find {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.svg.png, override ~/video.png manually" - cp {{ emacsconf_caption_dir }}/assets/overlays/blank-video.svg.png ~/video.png + echo "Could not find {{ emacsconf_caption_dir }}/assets/overlays/$SLUG-video.png, override ~/video.png manually" + cp {{ emacsconf_caption_dir }}/assets/overlays/blank-video.png ~/video.png fi diff --git a/roles/pad-proxy/tasks/main.yml b/roles/pad-proxy/tasks/main.yml index 8de72df..1e4518a 100644 --- a/roles/pad-proxy/tasks/main.yml +++ b/roles/pad-proxy/tasks/main.yml @@ -2,6 +2,10 @@ - name: Set up Nginx as root become: true block: + - name: Remove apache + apt: + name: apache2 + state: absent - name: Install Nginx apt: name: nginx diff --git a/roles/pad-proxy/templates/etherpad.nginx.conf b/roles/pad-proxy/templates/etherpad.nginx.conf index 144185f..b657b98 100644 --- a/roles/pad-proxy/templates/etherpad.nginx.conf +++ b/roles/pad-proxy/templates/etherpad.nginx.conf @@ -20,7 +20,7 @@ server { include {{ etherpad_tls }}; {% endif %} access_log /var/log/nginx/{{ etherpad_server_name }}.access.log; - location ~ ^/(locales/|locales.json|admin/|static/|pluginfw/|javascripts/|socket.io/|ep/|minified/|api/|ro/|error/|jserror/|favicon.ico|robots.txt) { + location ~ ^/(locales/|locales.json|admin/|static/|pluginfw/|javascripts/|socket.io/|ep/|minified/|api/|ro/|error/|jserror/|favicon.ico|robots.txt|.*\.js) { proxy_buffering off; proxy_pass http://etherpad_upstream; } @@ -49,7 +49,7 @@ server { proxy_pass http://etherpad_upstream; } location / { - rewrite ^/?$ https://pad.emacsconf.org/{{ emacsconf_year }} redirect; + rewrite ^/?$ {{ etherpad_url }}/{{ emacsconf_year }} redirect; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; diff --git a/roles/pad/defaults/main.yml b/roles/pad/defaults/main.yml index 7538489..7562410 100644 --- a/roles/pad/defaults/main.yml +++ b/roles/pad/defaults/main.yml @@ -1,10 +1,2 @@ --- # defaults file for pad -etherpad_path: /home/etherpad/etherpad -etherpad_database_name: emacsconf_pad -etherpad_database_user: etherpad -etherpad_user: etherpad -etherpad_group: etherpad -etherpad_base: emacsconf -etherpad_year: "{{ emacsconf_year }}" -etherpad_load_test: false diff --git a/roles/pad/tasks/main.yml b/roles/pad/tasks/main.yml index 103ba14..6e32ff6 100644 --- a/roles/pad/tasks/main.yml +++ b/roles/pad/tasks/main.yml @@ -1,10 +1,11 @@ --- # tasks file for pad - name: Set up packages as root + become: true block: - name: Add GPG apt: - update_cache: yes + update_cache: "{{ update_cache }}" name: - gpg - sudo @@ -16,15 +17,15 @@ - name: Add nodesource repository ansible.builtin.apt_repository: repo: deb https://deb.nodesource.com/node_20.x nodistro main - update_cache: yes + update_cache: "{{ update_cache }}" - name: Install packages apt: - update_cache: yes + update_cache: "{{ update_cache }}" name: - git - systemd - sudo - - nodejs + - nodejs=20.19.5-1nodesource1 - mariadb-server - mariadb-client state: present @@ -34,65 +35,106 @@ home: /home/etherpad shell: /bin/bash state: present -- import_tasks: mariadb.yml - become: true -- name: Set up etherpad as the etherpad user - tags: etherpad-src - become: true - become_user: "{{ etherpad_user }}" - block: - - name: Install etherpad - git: - repo: https://github.com/ether/etherpad-lite.git - dest: "{{ etherpad_path }}" - depth: 1 - - name: Configure etherpad - template: - src: templates/settings.json - dest: "{{ etherpad_path }}/settings.json" - - name: Install dependencies - shell: cd {{ etherpad_path }}; . src/bin/functions.sh; src/bin/installDeps.sh - # - name: Install etherpad plugins - # npm: - # name: ep_scrolltoanchor - # path: "{{ etherpad_path }}" - - name: Change ownership - file: - dest: /home/etherpad/etherpad - owner: "{{ etherpad_user }}" - group: "{{ etherpad_group }}" - recurse: true - - name: Set etherpad API key - copy: - content: "{{ etherpad_api_key }}" - dest: "{{ etherpad_path }}/APIKEY.txt" - owner: "{{ etherpad_user }}" - mode: "0600" -- name: Install init.d configuration - tags: system - become: true - template: - src: etherpad.init.d - dest: /etc/init.d/etherpad - owner: root - group: root - mode: 0755 - when: use_initd -- name: Install systemd configuration - tags: system - become: true - template: - src: etherpad.service - dest: /etc/systemd/system/etherpad.service - owner: root - group: root - mode: 0755 - when: not use_initd + - name: Install pnpm + community.general.npm: + name: pnpm + global: true + - name: Install Etherpad + include_role: + name: systemli.etherpad + - name: Install MySQL packages + apt: + name: + - mariadb-server + - mariadb-client + - python3-mysqldb + state: present + - name: Ensure mysql is configured to bind only to localhost + ini_file: + dest: /etc/mysql/my.cnf + section: mysqld + option: "bind-address" + value: "127.0.0.1" + - name: Ensure anonymous users are not in the database + mysql_user: + name: "" + host: "{{ item }}" + state: absent + with_items: + - localhost + - 127.0.0.1 + - ::1 + - "%" + - name: Start MariaDB + service: + name: mysql + state: restarted + enabled: yes + runlevel: + - 3 + - 5 + +# - import_tasks: mariadb.yml +# become: true +# - name: Set up etherpad as the etherpad user +# tags: etherpad-src +# become: true +# become_user: "{{ etherpad_user }}" +# block: +# - name: Install etherpad +# git: +# repo: https://github.com/ether/etherpad-lite.git +# dest: "{{ etherpad_path }}" +# version: v1.9.7 +# depth: 1 +# - name: Configure etherpad +# template: +# src: templates/settings.json +# dest: "{{ etherpad_path }}/settings.json" +# - name: Install dependencies +# shell: cd {{ etherpad_path }}; . src/bin/functions.sh; src/bin/installDeps.sh +# # - name: Install etherpad plugins +# # npm: +# # name: ep_scrolltoanchor +# # path: "{{ etherpad_path }}" +# - name: Change ownership +# file: +# dest: /home/etherpad/etherpad +# owner: "{{ etherpad_user }}" +# group: "{{ etherpad_group }}" +# recurse: true +# - name: Set etherpad API key +# copy: +# content: "{{ etherpad_api_key }}" +# dest: "{{ etherpad_path }}/APIKEY.txt" +# owner: "{{ etherpad_user }}" +# mode: "0600" +# - name: Install init.d configuration +# tags: system +# become: true +# template: +# src: etherpad.init.d +# dest: /etc/init.d/etherpad +# owner: root +# group: root +# mode: 0755 +# when: use_initd +# - name: Install systemd configuration +# tags: system +# become: true +# template: +# src: etherpad.service +# dest: /etc/systemd/system/etherpad.service +# owner: root +# group: root +# mode: 0755 +# when: not use_initd - name: Restart Etherpad become: true service: - name: etherpad + name: etherpad-lite state: restarted + enabled: yes - tags: create-pads include_vars: file: talks.json @@ -104,7 +146,7 @@ - name: Wait for OK tags: create-pads uri: - url: "https://{{ etherpad_server_name }}/api/1/createPad?apikey={{ etherpad_api_key }}&padID={{etherpad_year}}" + url: "{{ etherpad_url }}/api/1/createPad?apikey={{ etherpad_api_key }}&padID={{etherpad_year}}" register: _result until: _result.status == 200 retries: 720 @@ -115,5 +157,5 @@ - name: Create pads tags: create-pads uri: - url: "https://{{ etherpad_server_name }}/api/1/createPad?apikey={{ etherpad_api_key }}&padID={{etherpad_year}}-{{ item.slug }}" + url: "{{ etherpad_url }}/api/1/createPad?apikey={{ etherpad_api_key }}&padID={{etherpad_year}}-{{ item.slug }}" loop: "{{ talks | json_query('talks[*]') }}" diff --git a/roles/pad/tasks/mariadb.yml b/roles/pad/tasks/mariadb.yml deleted file mode 100644 index ec81430..0000000 --- a/roles/pad/tasks/mariadb.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- -- name: Install MySQL packages - apt: - name: - - mariadb-server - - mariadb-client - - python3-mysqldb -- name: Ensure mysql is configured to bind only to localhost - ini_file: - dest: /etc/mysql/my.cnf - section: mysqld - option: "bind-address" - value: "127.0.0.1" -- name: Start MariaDB - service: - name: mysql - state: restarted - enabled: yes - runlevel: - - 3 - - 5 -- name: Ensure anonymous users are not in the database - mysql_user: - name: "" - host: "{{ item }}" - state: absent - with_items: - - localhost - - 127.0.0.1 - - ::1 - - "%" -- name: Ensure emacsconf-pad database exists - mysql_db: - name: "{{ etherpad_database_name }}" - collation: utf8mb4_general_ci - state: present -- name: Grant permissions to user - mysql_user: - name: "{{ etherpad_database_user }}" - state: present - priv: "{{ etherpad_database_name }}.*:ALL" - password: "{{ etherpad_database_password }}" diff --git a/roles/pad/templates/etherpad.init.d b/roles/pad/templates/etherpad.init.d deleted file mode 100755 index 299d5fb..0000000 --- a/roles/pad/templates/etherpad.init.d +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/sh -# {{ ansible_managed }} - -### BEGIN INIT INFO -# Provides: etherpad-lite -# Required-Start: $local_fs $remote_fs $network $syslog -# Required-Stop: $local_fs $remote_fs $network $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: starts etherpad lite -# Description: starts etherpad lite using start-stop-daemon -### END INIT INFO - -PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" -LOGFILE="{{ etherpad_path }}/etherpad-lite.log" -EPLITE_DIR="{{ etherpad_path }}" -EPLITE_BIN="src/bin/safeRun.sh" -USER="{{ etherpad_user }}" -GROUP="{{ etherpad_group }}" -DESC="Etherpad Lite" -NAME="etherpad" - -set -e - -. /lib/lsb/init-functions - -start() { - echo "Starting $DESC... " - - start-stop-daemon --start --chuid "$USER:$GROUP" -d $EPLITE_DIR --background --make-pidfile --pidfile /var/run/$NAME.pid --exec $EPLITE_DIR/$EPLITE_BIN -- $LOGFILE || true - echo "done" -} - -#We need this function to ensure the whole process tree will be killed -killtree() { - local _pid=$1 - local _sig=${2-TERM} - for _child in $(ps -o pid --no-headers --ppid ${_pid}); do - killtree ${_child} ${_sig} - done - kill -${_sig} ${_pid} -} - -stop() { - echo "Stopping $DESC... " - if test -f /var/run/$NAME.pid; then - while test -d /proc/$(cat /var/run/$NAME.pid); do - killtree $(cat /var/run/$NAME.pid) 15 - sleep 0.5 - done - rm /var/run/$NAME.pid - fi - echo "done" -} - -status() { - status_of_proc -p /var/run/$NAME.pid "" "etherpad-lite" && exit 0 || exit $? -} - -case "$1" in - start) - start - ;; - stop) - stop - ;; - restart) - stop - start - ;; - status) - status - ;; - *) - echo "Usage: $NAME {start|stop|restart|status}" >&2 - exit 1 - ;; -esac - -exit 0 diff --git a/roles/pad/templates/etherpad.service b/roles/pad/templates/etherpad.service deleted file mode 100644 index bcc45d1..0000000 --- a/roles/pad/templates/etherpad.service +++ /dev/null @@ -1,17 +0,0 @@ -# {{ ansible_managed }} - -[Unit] -Description=Etherpad -After=syslog.target network.target - -[Service] -Type=simple -User={{ etherpad_user }} -Group={{ etherpad_group }} -WorkingDirectory={{ etherpad_path }} -ExecStart=node {{ etherpad_path }}/node_modules/ep_etherpad-lite/node/server.js -Environment=NODE_ENV=production -Restart=always - -[Install] -WantedBy=multi-user.target diff --git a/roles/pad/templates/settings.json b/roles/pad/templates/settings.json deleted file mode 100644 index 977a562..0000000 --- a/roles/pad/templates/settings.json +++ /dev/null @@ -1,634 +0,0 @@ -/* - * {{ ansible_managed }} - * - * This file must be valid JSON. But comments are allowed - * - * Please edit settings.json, not settings.json.template - * - * Please note that starting from Etherpad 1.6.0 you can store DB credentials in - * a separate file (credentials.json). - * - * - * ENVIRONMENT VARIABLE SUBSTITUTION - * ================================= - * - * All the configuration values can be read from environment variables using the - * syntax "${ENV_VAR}" or "${ENV_VAR:default_value}". - * - * This is useful, for example, when running in a Docker container. - * - * DETAILED RULES: - * - If the environment variable is set to the string "true" or "false", the - * value becomes Boolean true or false. - * - If the environment variable is set to the string "null", the value - * becomes null. - * - If the environment variable is set to the string "undefined", the setting - * is removed entirely, except when used as the member of an array in which - * case it becomes null. - * - If the environment variable is set to a string representation of a finite - * number, the string is converted to that number. - * - If the environment variable is set to any other string, including the - * empty string, the value is that string. - * - If the environment variable is unset and a default value is provided, the - * value is as if the environment variable was set to the provided default: - * - "${UNSET_VAR:}" becomes the empty string. - * - "${UNSET_VAR:foo}" becomes the string "foo". - * - "${UNSET_VAR:true}" and "${UNSET_VAR:false}" become true and false. - * - "${UNSET_VAR:null}" becomes null. - * - "${UNSET_VAR:undefined}" causes the setting to be removed (or be set - * to null, if used as a member of an array). - * - If the environment variable is unset and no default value is provided, - * the value becomes null. THIS BEHAVIOR MAY CHANGE IN A FUTURE VERSION OF - * ETHERPAD; if you want the default value to be null, you should explicitly - * specify "null" as the default value. - * - * EXAMPLE: - * "port": "${PORT:9001}" - * "minify": "${MINIFY}" - * "skinName": "${SKIN_NAME:colibris}" - * - * Would read the configuration values for those items from the environment - * variables PORT, MINIFY and SKIN_NAME. - * - * If PORT and SKIN_NAME variables were not defined, the default values 9001 and - * "colibris" would be used. - * The configuration value "minify", on the other hand, does not have a - * designated default value. Thus, if the environment variable MINIFY were - * undefined, "minify" would be null. - * - * REMARKS: - * 1) please note that variable substitution always needs to be quoted. - * - * "port": 9001, <-- Literal values. When not using - * "minify": false substitution, only strings must be - * "skinName": "colibris" quoted. Booleans and numbers must not. - * - * "port": "${PORT:9001}" <-- CORRECT: if you want to use a variable - * "minify": "${MINIFY:true}" substitution, put quotes around its name, - * "skinName": "${SKIN_NAME}" even if the required value is a number or - * a boolean. - * Etherpad will take care of rewriting it - * to the proper type if necessary. - * - * "port": ${PORT:9001} <-- ERROR: this is not valid json. Quotes - * "minify": ${MINIFY} around variable names are missing. - * "skinName": ${SKIN_NAME} - * - * 2) Beware of undefined variables and default values: nulls and empty strings - * are different! - * - * This is particularly important for user's passwords (see the relevant - * section): - * - * "password": "${PASSW}" // if PASSW is not defined would result in password === null - * "password": "${PASSW:}" // if PASSW is not defined would result in password === '' - * - * If you want to use an empty value (null) as default value for a variable, - * simply do not set it, without putting any colons: "${ABIWORD}". - * - * 3) if you want to use newlines in the default value of a string parameter, - * use "\n" as usual. - * - * "defaultPadText" : "${DEFAULT_PAD_TEXT}Line 1\nLine 2" - */ -{ - /* - * Name your instance! - */ - "title": "EmacsConf Etherpad", - - /* - * Pathname of the favicon you want to use. If null, the skin's favicon is - * used if one is provided by the skin, otherwise the default Etherpad favicon - * is used. If this is a relative path it is interpreted as relative to the - * Etherpad root directory. - */ - "favicon": null, - - /* - * Skin name. - * - * Its value has to be an existing directory under src/static/skins. - * You can write your own, or use one of the included ones: - * - * - "no-skin": an empty skin (default). This yields the unmodified, - * traditional Etherpad theme. - * - "colibris": the new experimental skin (since Etherpad 1.8), candidate to - * become the default in Etherpad 2.0 - */ - "skinName": "colibris", - - /* - * Skin Variants - * - * Use the UI skin variants builder at /p/test#skinvariantsbuilder - * - * For the colibris skin only, you can choose how to render the three main - * containers: - * - toolbar (top menu with icons) - * - editor (containing the text of the pad) - * - background (area outside of editor, mostly visible when using page style) - * - * For each of the 3 containers you can choose 4 color combinations: - * super-light, light, dark, super-dark. - * - * For example, to make the toolbar dark, you will include "dark-toolbar" into - * skinVariants. - * - * You can provide multiple skin variants separated by spaces. Default - * skinVariant is "super-light-toolbar super-light-editor light-background". - * - * For the editor container, you can also make it full width by adding - * "full-width-editor" variant (by default editor is rendered as a page, with - * a max-width of 900px). - */ - "skinVariants": "super-light-toolbar super-light-editor light-background", - - /* - * IP and port which Etherpad should bind at. - * - * Binding to a Unix socket is also supported: just use an empty string for - * the ip, and put the full path to the socket in the port parameter. - * - * EXAMPLE USING UNIX SOCKET: - * "ip": "", // <-- has to be an empty string - * "port" : "/somepath/etherpad.socket", // <-- path to a Unix socket - */ - "ip": "127.0.0.1", - "port": 9001, - - /* - * Option to hide/show the settings.json in admin page. - * - * Default option is set to true - */ - "showSettingsInAdminPage": true, - - /* - * Node native SSL support - * - * This is disabled by default. - * Make sure to have the minimum and correct file access permissions set so - * that the Etherpad server can access them - */ - - /* - "ssl" : { - "key" : "/path-to-your/epl-server.key", - "cert" : "/path-to-your/epl-server.crt", - "ca": ["/path-to-your/epl-intermediate-cert1.crt", "/path-to-your/epl-intermediate-cert2.crt"] - }, - */ - - /* - * The type of the database. - * - * You can choose between many DB drivers, for example: dirty, postgres, - * sqlite, mysql. - * - * You shouldn't use "dirty" for for anything else than testing or - * development. - * - * - * Database specific settings are dependent on dbType, and go in dbSettings. - * Remember that since Etherpad 1.6.0 you can also store this information in - * credentials.json. - * - * For a complete list of the supported drivers, please refer to: - * https://www.npmjs.com/package/ueberdb2 - */ - - /* - * An Example of MySQL Configuration (commented out). - * - * See: https://github.com/ether/etherpad-lite/wiki/How-to-use-Etherpad-Lite-with-MySQL - */ - - "dbType" : "mysql", - "dbSettings" : { - "user": "{{ etherpad_database_user }}", - "host": "localhost", - "port": 3306, - "password": "{{ etherpad_database_password }}", - "database": "{{ etherpad_database_name }}", - "charset": "utf8mb4" - }, - - /* - * The default text of a pad - */ - "defaultPadText" : "Conference info, how to watch/participate: https://emacsconf.org/{{ emacsconf_year }}/\nGuidelines for conduct: https://emacsconf.org/conduct/\nSee end of file for license (CC Attribution-ShareAlike 4.0 + GPLv3 or later)\n----------------------------------------------------------------\nQuestions and discussion go here:\n- \n- \n- \n- \n- \n- \n- \n\n----------------------------------------------------------------\nExcept where otherwise noted, the material on the EmacsConf pad are dual-licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International Public License; and the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) an later version. Copies of these two licenses are included in the EmacsConf wiki repository, in the COPYING.GPL and COPYING.CC-BY-SA files (https://emacsconf.org/COPYING/)\n\nBy contributing to this pad, you agree to make your contributions available under the above licenses. You are also promising that you are the author of your changes, or that you copied them from a work in the public domain or a work released under a free license that is compatible with the above two licenses. DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION.", - - /* - * Default Pad behavior. - * - * Change them if you want to override. - */ - "padOptions": { - "noColors": false, - "showControls": true, - "showChat": false, - "showLineNumbers": true, - "useMonospaceFont": false, - "userName": null, - "userColor": null, - "rtl": false, - "alwaysShowChat": false, - "chatAndUsers": false, - "lang": null - }, - - /* - * Pad Shortcut Keys - */ - "padShortcutEnabled" : { - "altF9": true, /* focus on the File Menu and/or editbar */ - "altC": true, /* focus on the Chat window */ - "cmdShift2": true, /* shows a gritter popup showing a line author */ - "delete": true, - "return": true, - "esc": true, /* in mozilla versions 14-19 avoid reconnecting pad */ - "cmdS": true, /* save a revision */ - "tab": true, /* indent */ - "cmdZ": true, /* undo/redo */ - "cmdY": true, /* redo */ - "cmdI": true, /* italic */ - "cmdB": true, /* bold */ - "cmdU": true, /* underline */ - "cmd5": true, /* strike through */ - "cmdShiftL": true, /* unordered list */ - "cmdShiftN": true, /* ordered list */ - "cmdShift1": true, /* ordered list */ - "cmdShiftC": true, /* clear authorship */ - "cmdH": true, /* backspace */ - "ctrlHome": true, /* scroll to top of pad */ - "pageUp": true, - "pageDown": true - }, - - /* - * Should we suppress errors from being visible in the default Pad Text? - */ - "suppressErrorsInPadText": false, - - /* - * If this option is enabled, a user must have a session to access pads. - * This effectively allows only group pads to be accessed. - */ - "requireSession": false, - - /* - * Users may edit pads but not create new ones. - * - * Pad creation is only via the API. - * This applies both to group pads and regular pads. - */ - "editOnly": {{ (not etherpad_load_test) | bool | lower }}, - - /* - * If true, all css & js will be minified before sending to the client. - * - * This will improve the loading performance massively, but makes it difficult - * to debug the javascript/css - */ - "minify": true, - - /* - * How long may clients use served javascript code (in seconds)? - * - * Not setting this may cause problems during deployment. - * Set to 0 to disable caching. - */ - "maxAge": 21600, // 60 * 60 * 6 = 6 hours - - /* - * Absolute path to the Abiword executable. - * - * Abiword is needed to get advanced import/export features of pads. Setting - * it to null disables Abiword and will only allow plain text and HTML - * import/exports. - */ - "abiword": null, - - /* - * This is the absolute path to the soffice executable. - * - * LibreOffice can be used in lieu of Abiword to export pads. - * Setting it to null disables LibreOffice exporting. - */ - "soffice": null, - - /* - * Path to the Tidy executable. - * - * Tidy is used to improve the quality of exported pads. - * Setting it to null disables Tidy. - */ - "tidyHtml": null, - - /* - * Allow import of file types other than the supported ones: - * txt, doc, docx, rtf, odt, html & htm - */ - "allowUnknownFileEnds": false, - - /* - * This setting is used if you require authentication of all users. - * - * Note: "/admin" always requires authentication. - */ - "requireAuthentication": false, - - /* - * Require authorization by a module, or a user with is_admin set, see below. - */ - "requireAuthorization": false, - - /* - * When you use NGINX or another proxy/load-balancer set this to true. - * - * This is especially necessary when the reverse proxy performs SSL - * termination, otherwise the cookies will not have the "secure" flag. - * - * The other effect will be that the logs will contain the real client's IP, - * instead of the reverse proxy's IP. - */ - "trustProxy": true, - - /* - * Settings controlling the session cookie issued by Etherpad. - */ - "cookie": { - /* - * Value of the SameSite cookie property. "Lax" is recommended unless - * Etherpad will be embedded in an iframe from another site, in which case - * this must be set to "None". Note: "None" will not work (the browser will - * not send the cookie to Etherpad) unless https is used to access Etherpad - * (either directly or via a reverse proxy with "trustProxy" set to true). - * - * "Strict" is not recommended because it has few security benefits but - * significant usability drawbacks vs. "Lax". See - * https://stackoverflow.com/q/41841880 for discussion. - */ - "sameSite": "Lax", - - /* - * How long (in milliseconds) after navigating away from Etherpad before the - * user is required to log in again. (The express_sid cookie is set to - * expire at time now + sessionLifetime when first created, and its - * expiration time is periodically refreshed to a new now + sessionLifetime - * value.) If requireAuthentication is false then this value does not really - * matter. - * - * The "best" value depends on your users' usage patterns and the amount of - * convenience you desire. A long lifetime is more convenient (users won't - * have to log back in as often) but has some drawbacks: - * - It increases the amount of state kept in the database. - * - It might weaken security somewhat: The cookie expiration is refreshed - * indefinitely without consulting authentication or authorization - * hooks, so once a user has accessed a pad, the user can continue to - * use the pad until the user leaves for longer than sessionLifetime. - * - * Session lifetime can be set to infinity (not recommended) by setting this - * to null or 0. Note that if the session does not expire, most browsers - * will delete the cookie when the browser exits, but a session record is - * kept in the database forever. - */ - "sessionLifetime": 864000000, // = 10d * 24h/d * 60m/h * 60s/m * 1000ms/s - - /* - * How long (in milliseconds) before the expiration time of an active user's - * session is refreshed (to now + sessionLifetime). This setting affects the - * following: - * - How often a new session expiration time will be written to the - * database. - * - How often each user's browser will ping the Etherpad server to - * refresh the expiration time of the session cookie. - * - * High values reduce the load on the database and the load from browsers, - * but can shorten the effective session lifetime if Etherpad is restarted - * or the user navigates away. - * - * Automatic session refreshes can be disabled (not recommended) by setting - * this to null. - */ - "sessionRefreshInterval": 86400000 // = 1d * 24h/d * 60m/h * 60s/m * 1000ms/s - }, - - /* - * Privacy: disable IP logging - */ - "disableIPlogging": true, - - /* - * Time (in seconds) to automatically reconnect pad when a "Force reconnect" - * message is shown to user. - * - * Set to 0 to disable automatic reconnection. - */ - "automaticReconnectionTimeout": 0, - - /* - * By default, when caret is moved out of viewport, it scrolls the minimum - * height needed to make this line visible. - */ - "scrollWhenFocusLineIsOutOfViewport": { - - /* - * Percentage of viewport height to be additionally scrolled. - * - * E.g.: use "percentage.editionAboveViewport": 0.5, to place caret line in - * the middle of viewport, when user edits a line above of the - * viewport - * - * Set to 0 to disable extra scrolling - */ - "percentage": { - "editionAboveViewport": 0, - "editionBelowViewport": 0 - }, - - /* - * Time (in milliseconds) used to animate the scroll transition. - * Set to 0 to disable animation - */ - "duration": 0, - - /* - * Flag to control if it should scroll when user places the caret in the - * last line of the viewport - */ - "scrollWhenCaretIsInTheLastLineOfViewport": false, - - /* - * Percentage of viewport height to be additionally scrolled when user - * presses arrow up in the line of the top of the viewport. - * - * Set to 0 to let the scroll to be handled as default by Etherpad - */ - "percentageToScrollWhenUserPressesArrowUp": 0 - }, - - /* - * User accounts. These accounts are used by: - * - default HTTP basic authentication if no plugin handles authentication - * - some but not all authentication plugins - * - some but not all authorization plugins - * - * User properties: - * - password: The user's password. Some authentication plugins will ignore - * this. - * - is_admin: true gives access to /admin. Defaults to false. If you do not - * uncomment this, /admin will not be available! - * - readOnly: If true, this user will not be able to create new pads or - * modify existing pads. Defaults to false. - * - canCreate: If this is true and readOnly is false, this user can create - * new pads. Defaults to true. - * - * Authentication and authorization plugins may define additional properties. - * - * WARNING: passwords should not be stored in plaintext in this file. - * If you want to mitigate this, please install ep_hash_auth and - * follow the section "secure your installation" in README.md - */ - - /* - "users": { - "admin": { - // 1) "password" can be replaced with "hash" if you install ep_hash_auth - // 2) please note that if password is null, the user will not be created - "password": "changeme1", - "is_admin": true - }, - "user": { - // 1) "password" can be replaced with "hash" if you install ep_hash_auth - // 2) please note that if password is null, the user will not be created - "password": "changeme1", - "is_admin": false - } - }, - */ - - /* - * Restrict socket.io transport methods - */ - "socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"], - - "socketIo": { - /* - * Maximum permitted client message size (in bytes). All messages from - * clients that are larger than this will be rejected. Large values make it - * possible to paste large amounts of text, and plugins may require a larger - * value to work properly, but increasing the value increases susceptibility - * to denial of service attacks (malicious clients can exhaust memory). - */ - "maxHttpBufferSize": 10000 - }, - - /* - * Allow Load Testing tools to hit the Etherpad Instance. - * - * WARNING: this will disable security on the instance. - */ - "loadTest": {{ etherpad_load_test | bool | lower }}, - - /** - * Disable dump of objects preventing a clean exit - */ - "dumpOnUncleanExit": false, - - /* - * Disable indentation on new line when previous line ends with some special - * chars (':', '[', '(', '{') - */ - - /* - "indentationOnNewLine": false, - */ - - /* - * From Etherpad 1.8.3 onwards, import and export of pads is always rate - * limited. - * - * The default is to allow at most 10 requests per IP in a 90 seconds window. - * After that the import/export request is rejected. - * - * See https://github.com/nfriedly/express-rate-limit for more options - */ - "importExportRateLimiting": { - // duration of the rate limit window (milliseconds) - "windowMs": 90000, - - // maximum number of requests per IP to allow during the rate limit window - "max": 10 - }, - - /* - * From Etherpad 1.8.3 onwards, the maximum allowed size for a single imported - * file is always bounded. - * - * File size is specified in bytes. Default is 50 MB. - */ - "importMaxFileSize": 52428800, // 50 * 1024 * 1024 - - /* - * From Etherpad 1.8.5 onwards, when Etherpad is in production mode commits from individual users are rate limited - * - * The default is to allow at most 10 changes per IP in a 1 second window. - * After that the change is rejected. - * - * See https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#websocket-single-connection-prevent-flooding for more options - */ - "commitRateLimiting": { - // duration of the rate limit window (seconds) - "duration": 1, - - // maximum number of changes per IP to allow during the rate limit window - "points": 10 - }, - - /* - * Toolbar buttons configuration. - * - * Uncomment to customize. - */ - - /* - "toolbar": { - "left": [ - ["bold", "italic", "underline", "strikethrough"], - ["orderedlist", "unorderedlist", "indent", "outdent"], - ["undo", "redo"], - ["clearauthorship"] - ], - "right": [ - ["importexport", "timeslider", "savedrevision"], - ["settings", "embed"], - ["showusers"] - ], - "timeslider": [ - ["timeslider_export", "timeslider_returnToPad"] - ] - }, - */ - - /* - * Expose Etherpad version in the web interface and in the Server http header. - * - * Do not enable on production machines. - */ - "exposeVersion": false, - - /* - * The log level we are using. - * - * Valid values: DEBUG, INFO, WARN, ERROR - */ - "loglevel": "INFO", - - /* Override any strings found in locale directories */ - "customLocaleStrings": {}, - - /* Disable Admin UI tests */ - "enableAdminUITests": false -} diff --git a/roles/pad/vars/main.yml b/roles/pad/vars/main.yml index 981efa9..dfe2bfc 100644 --- a/roles/pad/vars/main.yml +++ b/roles/pad/vars/main.yml @@ -1,2 +1,20 @@ ---- -# vars file for pad +etherpad_user: etherpad +etherpad_group: etherpad +etherpad_base: emacsconf +etherpad_year: "{{ emacsconf_year }}" +etherpad_load_test: "false" +etherpad_title: "{{emacsconf_name}} {{emacsconf_year}}" +etherpad_enable_metrics: true +etherpad_default_text: "Conference info, how to watch/participate: https://emacsconf.org/{{ emacsconf_year }}/\\nGuidelines for conduct: https://emacsconf.org/conduct/\\nSee end of file for license (CC Attribution-ShareAlike 4.0 + GPLv3 or later)\\n----------------------------------------------------------------\\nQuestions and discussion go here:\\n- \\n- \\n- \\n- \\n- \\n- \\n- \\n\\n----------------------------------------------------------------\\nExcept where otherwise noted, the material on the EmacsConf pad are dual-licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International Public License; and the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) an later version. Copies of these two licenses are included in the EmacsConf wiki repository, in the COPYING.GPL and COPYING.CC-BY-SA files (https://emacsconf.org/COPYING/)\\n\\nBy contributing to this pad, you agree to make your contributions available under the above licenses. You are also promising that you are the author of your changes, or that you copied them from a work in the public domain or a work released under a free license that is compatible with the above two licenses. DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION." +etherpad_pad_options_no_colors: "false" +etherpad_pad_options_show_controls: "true" +etherpad_pad_options_show_chat: "false" +etherpad_abiword: null +etherpad_soffice: "null" +etherpad_edit_only: "true" +etherpad_mysql_database_user: etherpad +etherpad_mysql_database_name: etherpad +etherpad_db_type: mysql +etherpad_mysql_database_host: localhost +etherpad_mysql_database_password: "{{ etherpad_database_password }}" +etherpad_min_node_version: "18.18.2" diff --git a/roles/prerec/tasks/main.yml b/roles/prerec/tasks/main.yml index 5b39977..a0a3cac 100644 --- a/roles/prerec/tasks/main.yml +++ b/roles/prerec/tasks/main.yml @@ -68,10 +68,11 @@ - verify-main.sh - remux.sh - get-file-prefix + - reencode-in-screen.sh - name: Copy Makefile + tags: process-prerec, prerec-scripts, prerec-make template: src: Makefile dest: "{{ emacsconf_caption_dir }}/cache/Makefile" owner: "{{ emacsconf_user }}" group: "{{ emacsconf_group }}" - diff --git a/roles/prerec/templates/Makefile b/roles/prerec/templates/Makefile index 94aa412..d841cda 100644 --- a/roles/prerec/templates/Makefile +++ b/roles/prerec/templates/Makefile @@ -1,16 +1,118 @@ # {{ ansible_managed }} -PRERECS_FINAL := $(wildcard {{ emacsconf_id }}-*--final.webm) -PRERECS_MAIN := $(patsubst %--final.webm, %--main.webm, $(PRERECS_FINAL)) +# To recreate this file, use ansible-playbook -i inventory.yml prod-playbook.yml --tags prerec-make + +VIDEO_EXTS = mp4 mkv webm mov mpv +source_patterns = $(foreach ext,$(VIDEO_EXTS),$(1)--original.$(ext)) + +PRERECS_ORIGINAL := $(wildcard emacsconf-*--original.*) +PREFIXES := $(shell for f in $(PRERECS_ORIGINAL); do echo "$${f%--original.*}"; done) +PRERECS_REENCODED := $(addsuffix --reencoded.webm, $(PREFIXES)) +PRERECS_OPUS := $(addsuffix --reencoded.opus, $(PREFIXES)) +PRERECS_MAIN := $(addsuffix --main.webm, $(PREFIXES)) +PRERECS_CAPTIONS := $(addsuffix --reencoded.vtt, $(PREFIXES)) +PRERECS_FINAL := $(wildcard emacsconf-*--final.webm) +LINODE_BBB_ID := 67329098 .PHONY: all -all: $(PRERECS_MAIN) $(PRERECS_FINAL) -emacsconf-%--main.webm: {{ emacsconf_id }}-%--final.webm +all: reencoded opus main + +reencoded: $(PRERECS_REENCODED) + +opus: $(PRERECS_OPUS) + +captions: $(PRERECS_CAPTIONS) + +main: $(PRERECS_MAIN) + +emacsconf-%--reencoded.webm: SOURCES = $(call source_patterns, emacsconf-$*) +emacsconf-%--reencoded.webm: + $(eval SOURCE := $(lastword $(sort $(wildcard $(SOURCES))))) + @if [ -z "$(SOURCE)" ]; then \ + echo "No source file found for $@"; \ + echo "Tried: $(SOURCES)"; \ + exit 1; \ + fi + @echo "Using source: $(SOURCE)" + reencode-in-screen.sh "$(SOURCE)" + +emacsconf-%--reencoded.opus: emacsconf-%--reencoded.webm + ffmpeg -y -i "$<" -c:a copy "$@" + +emacsconf-%--answers.opus: emacsconf-%--answers.webm + ffmpeg -y -i "$<" -c:a copy "$@" + +# emacsconf-%--normalized.opus: emacsconf-%--reencoded.opus +# ffmpeg-normalize "$<" -ofmt opus -c:a libopus -o "$@" + +emacsconf-%--main.webm: emacsconf-%--reencoded.webm emacsconf-%--normalized.opus emacsconf-%--main.vtt + ffmpeg -i emacsconf-$*--reencoded.webm -i emacsconf-$*--normalized.opus -i emacsconf-$*--main.vtt \ + -map 0:v -map 1:a -c:v copy -c:a copy \ + -map 2 -c:s webvtt -y \ + $@ + +emacsconf-%--main.webm: emacsconf-%--reencoded.webm emacsconf-%--normalized.opus + ffmpeg -i emacsconf-$*--reencoded.webm -i emacsconf-$*--normalized.opus \ + -map 0:v -map 1:a -c:v copy -c:a copy \ + -y $@ + +emacsconf-%--main.webm: emacsconf-%--reencoded.webm cp "$<" "$@" -emacsconf-%--final.webm: {{ emacsconf_id }}-%--main.vtt +emacsconf-%--final.webm: emacsconf-%--main.vtt mux-subs.sh "$@" "$<" +emacsconf-%--main.opus: emacsconf-%--main.webm + ffmpeg -y -i "$<" -c:a copy "$@" + +emacsconf-%--reencoded.vtt: emacsconf-%--reencoded.opus + whisperx --model large-v3 --align_model WAV2VEC2_ASR_LARGE_LV60K_960H --compute_type int8 --print_progress True --max_line_width 50 --segment_resolution chunk --max_line_count 1 --language en "$<" + +emacsconf-%--backstage--silences.csv: emacsconf-%--reencoded.opus + ffmpeg -i "$<" -af silencedetect=noise=-30dB:d=0.5 -f null - 2>&1 | awk '/silence_start/ {start=$$NF} /silence_end/ {print start "," (start + $$NF)}' > "$@" + +show-files: + @echo "Original $(words $(PRERECS_ORIGINAL)):" + @echo "$(PRERECS_ORIGINAL)" + @echo "Prefixes $(words $(PREFIXES)):" + @echo "$(PREFIXES)" + @echo "Reencoded $(words $(PRERECS_REENCODED)):" + @echo "$(PRERECS_REENCODED)" + @echo "Opus $(words $(PRERECS_OPUS)):" + @echo "$(PRERECS_OPUS)" + +bbb-testing: + @echo "Resizing BBB node to 8GB 4 core for testing" + linode-cli linodes resize $(LINODE_BBB_ID) --type g6-standard-4 --allow_auto_disk_resize false + sleep 2m + @echo "Booting up" + linode-cli linodes boot $(LINODE_BBB_ID) + ssh root@bbb.emacsverse.org "cd ~/greenlight-v3; docker compose restart" + +bbb-dormant: + @echo "Shutting down" + ssh root@bbb.emacsverse.org "/usr/sbin/shutdown -h now &" || true + sleep 30 + @echo "Powering off BBB node" + linode-cli linodes shutdown $(LINODE_BBB_ID) + sleep 30 + @echo "Resizing BBB node to nanode, dormant" + linode-cli linodes resize $(LINODE_BBB_ID) --type g6-nanode-1 --allow_auto_disk_resize false + +bbb-prod: + @echo "Resizing BBB node to production size" + linode-cli linodes resize $(LINODE_BBB_ID) --type g6-dedicated-8 --allow_auto_disk_resize true + sleep 2m + @echo "Booting up" + linode-cli linodes boot $(LINODE_BBB_ID) + +live-dormant: + @echo "Resizing live0 node to nanode, dormant" + linode-cli linodes resize 17921960 --type g6-nanode-1 --allow_auto_disk_resize false + sleep 120 + linode-cli linodes boot 17921960 + + rsync: rsync -avzue ssh {{ emacsconf_caption_dir }}/cache/ orga@media.emacsconf.org:/var/www/media.emacsconf.org/{{ emacsconf_year }}/backstage/ diff --git a/roles/prerec/templates/copy-original.sh b/roles/prerec/templates/copy-original.sh new file mode 100755 index 0000000..854bdb8 --- /dev/null +++ b/roles/prerec/templates/copy-original.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# {{ ansible_managed }} +# Usage: rename-original.sh $slug $file [$extra] +SLUG=$1 +FILE=$2 +EXTRA="" +if [ -z ${3-unset} ]; then + EXTRA="" +elif [ -n "$3" ]; then + EXTRA="$3" +elif echo "$FILE" | grep -e '\(webm\|mp4\|mov\)'; then + EXTRA="--original" +fi +filename=$(basename -- "$FILE") +extension="${filename##*.}" +filename="${filename%.*}" +FILE_PREFIX=$(get-file-prefix $SLUG) +if echo "$FILE" | grep -q \\. ; then + cp "$FILE" $FILE_PREFIX$EXTRA.$extension + echo $FILE_PREFIX$EXTRA.$extension +else + cp "$FILE" $FILE_PREFIX$EXTRA + echo $FILE_PREFIX$EXTRA +fi diff --git a/roles/prerec/templates/get-file-prefix b/roles/prerec/templates/get-file-prefix new file mode 100755 index 0000000..0240b99 --- /dev/null +++ b/roles/prerec/templates/get-file-prefix @@ -0,0 +1,10 @@ +#!/bin/bash +# {{ ansible_managed }} +# Usage: get-file-prefix $slug [talks.json] +# You can also set the TALKS_JSON environment variable + +SLUG=$1 +if [ -z "$TALKS_JSON" ]; then + TALKS_JSON=${2:-~orga/current/talks.json} +fi +jq -r '.talks[] | select(.slug=="'$SLUG'")["file-prefix"]' < $TALKS_JSON diff --git a/roles/prerec/templates/process-prerec.sh b/roles/prerec/templates/process-prerec.sh index d98337f..d0f5fa7 100755 --- a/roles/prerec/templates/process-prerec.sh +++ b/roles/prerec/templates/process-prerec.sh @@ -5,9 +5,10 @@ ORIGINAL=$1 REENCODED=$(echo "$ORIGINAL" | perl -pe 's/^(emacsconf-[0-9]*-.*?--.*?--.*?--).*/$1reencoded.webm/') SLUG=$(echo "$ORIGINAL" | perl -ne '/^emacsconf-[0-9]*-(.*?)--/ && print $1') MAIN=$(echo "$ORIGINAL" | perl -pe 's/^(emacsconf-[0-9]*-.*?--.*?--.*?--).*/$1main.webm/') +VTT=$(echo "$ORIGINAL" | perl -pe 's/^(emacsconf-[0-9]*-.*?--.*?--.*?--).*/$1main.vtt/') # ( cd /data/emacsconf/cache; ./update-cache ) # /data/emacsconf/admin/{{ emacsconf_year }}/scripts/talk $SLUG "WAITING_FOR_PREREC" "PROCESSING" if [[ ! -f "$REENCODED" ]]; then screen -dmS reencode-$SLUG /bin/bash -c "reencode.sh \"$ORIGINAL\" \"$REENCODED\" && upload.sh $REENCODED $MAIN && thumbnail.sh \"$MAIN\" && upload.sh $(echo "$MAIN" | sed s/webm$/png/); echo $(date -Iminutes) $SLUG reencoded >> ~/emacsconf.log && exec /bin/bash" & fi -screen -dmS captions-$SLUG /bin/bash -c "/data/emacsconf/admin/{{ emacsconf_year }}/scripts/process-captions.py $(dirname $ORIGINAL); echo $(date -Iminutes) $SLUG captioned >> ~/emacsconf.log; exec /bin/bash" +screen -dmS captions-$SLUG /bin/bash -c "make $VTT; echo $(date -Iminutes) $SLUG captioned >> ~/emacsconf.log; exec /bin/bash" diff --git a/roles/prerec/templates/reencode-in-screen.sh b/roles/prerec/templates/reencode-in-screen.sh new file mode 100755 index 0000000..5c12203 --- /dev/null +++ b/roles/prerec/templates/reencode-in-screen.sh @@ -0,0 +1,16 @@ +#!/bin/bash +ORIGINAL=$1 +BASE="${ORIGINAL%--original.*}" +REENCODED="${BASE}--reencoded.webm" +SLUG=$(echo "$ORIGINAL" | perl -ne '/^emacsconf-[0-9]*-(.*?)--/ && print $1') +LOCK=".lock-$SLUG" + +if [ ! -f "$REENCODED" ]; then + if [ -f "$LOCK" ]; then + echo "$LOCK already exists, waiting for it" + else + touch "$LOCK" + screen -dmS reencode-$SLUG /bin/bash -c "reencode.sh \"$ORIGINAL\" \"$REENCODED\" && thumbnail.sh \"$MAIN\" && rm \"$LOCK\"" + echo "Processing $REENCODED in reencode-$SLUG" + fi +fi diff --git a/roles/prerec/templates/upload.sh b/roles/prerec/templates/upload.sh index fbf3025..09d55d9 100755 --- a/roles/prerec/templates/upload.sh +++ b/roles/prerec/templates/upload.sh @@ -2,5 +2,5 @@ # {{ ansible_managed }} scp $* orga@media.emacsconf.org:~/backstage -/data/emacsconf/admin/{{ emacsconf_year }}/scripts/publish-backstage-index.sh -rsync -avze ssh orga@media.emacsconf.org:~/backstage/ /data/emacsconf/admin/cache/ +/usr/local/bin/publish-backstage-index.sh +rsync -avze ssh orga@media.emacsconf.org:~/backstage/ /data/emacsconf/shared/{{ emacsconf_year }}/cache/ diff --git a/roles/publish/tasks/emacs.yml b/roles/publish/tasks/emacs.yml index 3944876..d961878 100644 --- a/roles/publish/tasks/emacs.yml +++ b/roles/publish/tasks/emacs.yml @@ -8,6 +8,8 @@ - pkg-config - libjansson-dev - libgnutls28-dev + - libtiff-dev + - libtiff5-dev - automake - texinfo state: present diff --git a/roles/publish/tasks/main.yml b/roles/publish/tasks/main.yml index 546a4f0..797ac7f 100644 --- a/roles/publish/tasks/main.yml +++ b/roles/publish/tasks/main.yml @@ -26,7 +26,7 @@ - name: Set up Emacs become: yes import_tasks: emacs.yml - when: not emacs.stat.exists + # when: not emacs.stat.exists - name: Configure git template: src: git-config diff --git a/roles/publish/templates/emacsconf-config.el b/roles/publish/templates/emacsconf-config.el index 05f705a..767de85 100644 --- a/roles/publish/templates/emacsconf-config.el +++ b/roles/publish/templates/emacsconf-config.el @@ -23,8 +23,8 @@ (setq emacsconf-upload-dir "/ssh:orga@media.emacsconf.org:/srv/upload") {% if ansible_host == "res.emacsconf.org" %} -(setq emacsconf-res-dir "/data/{{ emacsconf_id }}/{{ emacsconf_year}}") -(setq emacsconf-cache-dir "/data/{{ emacsconf_id }}/cache") +(setq emacsconf-res-dir "/data/{{ emacsconf_id }}/shared/{{ emacsconf_year}}") +(setq emacsconf-cache-dir "/data/{{ emacsconf_id }}/shared/{{ emacsconf_year}}/cache") (setq emacsconf-stream-host "localhost") (setq emacsconf-stream-overlay-dir "{{ emacsconf_caption_dir }}/assets/overlays") (setq emacsconf-stream-asset-dir "{{ emacsconf_caption_dir }}/assets") diff --git a/roles/stream/templates/lowres.sh b/roles/stream/templates/lowres.sh index 502fcb3..13d6a81 100755 --- a/roles/stream/templates/lowres.sh +++ b/roles/stream/templates/lowres.sh @@ -1,6 +1,6 @@ #!/bin/bash # {{ ansible_managed }} sleep 10 -for i in 1 2 3 4 5; do +while true; do ffmpeg -loglevel 24 -f webm -reconnect_at_eof 1 -reconnect_streamed 1 -re -i "http://localhost:{{ icecast_port }}/{{ item.id }}.webm" -vf scale="{{ icecast_lowres_scale }}" -f webm -c:a copy -b:v 500k -maxrate 1M -bufsize 1M -content_type video/webm -c:v libvpx "icecast://{{ icecast_emacsconf_user }}:{{ icecast_emacsconf_password }}@localhost:{{ icecast_port }}/{{ item.id }}-480p.webm" >> {{ icecast_restream_dir }}/{{ emacsconf_id }}-lowres-{{ item.id }}.log || sleep 5 done diff --git a/roles/upload/tasks/main.yml b/roles/upload/tasks/main.yml index ca87a1c..b63e3f1 100644 --- a/roles/upload/tasks/main.yml +++ b/roles/upload/tasks/main.yml @@ -21,6 +21,14 @@ name: - nodejs state: present +- name: Add to dehydrated.conf + become: true + lineinfile: + line: "{{ upload_server_name }}" + path: /etc/dehydrated/domains.txt +- name: Create or renew cert + command: "dehydrated --cron" + become: true - name: Create upload user become: true user: @@ -99,6 +107,19 @@ owner: "{{ upload_user }}" group: "{{ upload_group }}" recurse: true +- name: Create backup dir to use when the conference is done + file: + path: "{{ upload_done_dir }}" + owner: "{{ upload_user }}" + group: "{{ upload_group }}" + state: directory +- name: Create backup file to use when the conference is done + template: + src: index.html + owner: "{{ upload_user }}" + group: "{{ upload_group }}" + mode: 0755 + dest: "{{ upload_done_dir }}/index.html" - name: Install systemd configuration tags: system become: true @@ -109,6 +130,23 @@ group: root mode: 0755 when: not use_initd +- name: Create main configuration if needed + template: + src: nginx-site-config + dest: /etc/nginx/sites-available/{{ upload_server_name }} +- name: Make sure main configuration is enabled + file: + src: /etc/nginx/sites-available/{{ upload_server_name }} + dest: /etc/nginx/sites-enabled/{{ upload_server_name }} + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + force: no + state: link +- name: Reload configuration + become: true + service: + name: nginx + state: reloaded - name: Restart Upload become: true when: upload_enabled diff --git a/roles/upload/templates/index.html b/roles/upload/templates/index.html new file mode 100644 index 0000000..e5d8e6e --- /dev/null +++ b/roles/upload/templates/index.html @@ -0,0 +1,7 @@ +<html> + <head> + </head> + <body> + EmacsConf is done for now, so we've turned off the file upload service. Let us know at <a href="mailto:emacsconf-org-private@gnu.org">emacsconf-org-private@gnu.org</a> if you need it back to upload something! + </body> +</html> diff --git a/roles/upload/templates/nginx-site-config b/roles/upload/templates/nginx-site-config new file mode 100644 index 0000000..48842d1 --- /dev/null +++ b/roles/upload/templates/nginx-site-config @@ -0,0 +1,46 @@ +upstream upload_emacsconf { + server 127.0.0.1:3000; +} + +server { + listen 80; + listen [::]:80; + server_name {{ upload_server_name }}; + + include snippets/well-known-acme-challenge.conf; + + location / { + return 302 https://$server_name$request_uri; + } +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name {{ upload_server_name }}; + + ssl_certificate /var/local/dehydrated/certs/{{ upload_server_name }}/fullchain.pem; + ssl_certificate_key /var/local/dehydrated/certs/{{ upload_server_name }}/privkey.pem; + ssl_trusted_certificate /var/local/dehydrated/certs/{{ upload_server_name }}/fullchain.pem; + include ssl_params.local; + include snippets/well-known-acme-challenge.conf; +{% if upload_enabled %} + location @upload_emacsconf { + proxy_pass http://upload_emacsconf; + proxy_http_version 1.1; + proxy_buffering off; + proxy_request_buffering off; # needs nginx version >= 1.7.11 + proxy_set_header Host $http_host; + } + location / { + #try_files $uri $uri/ @upload_emacsconf; + proxy_pass http://upload_emacsconf; + proxy_http_version 1.1; + proxy_buffering off; + proxy_request_buffering off; # needs nginx version >= 1.7.11 + proxy_set_header Host $http_host; + } + {% else %} + root {{ upload_done_dir }}; + {% endif %} +} diff --git a/roles/wiki/templates/emacsconf.setup b/roles/wiki/templates/emacsconf.setup index 2cb114f..a7d2377 100644 --- a/roles/wiki/templates/emacsconf.setup +++ b/roles/wiki/templates/emacsconf.setup @@ -200,7 +200,7 @@ atom: 1 # PageSpec controlling which pages are locked #locked_pages: '!*/Discussion' #locked_pages: 'index or edit' -locked_pages: 'edit or donate or donors' +locked_pages: 'edit or donate or donors or script.js or local.css or templates/page.tmpl' # moderatedcomments plugin # PageSpec matching users or comment locations to moderate |
