diff --git a/.dockerignore b/.dockerignore index 46d5d75a7..84fb24f8b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -37,3 +37,5 @@ pip-log.txt .sass-cache/* node_modules venv + +docker-compose.* diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml new file mode 100644 index 000000000..794775c83 --- /dev/null +++ b/.github/workflows/docker-build.yaml @@ -0,0 +1,36 @@ +name: Docker Image Build + +on: + push: + branches: + - master + - production + - experimental + - experimental-fixes + +jobs: + buildx: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up Docker Buildx + id: buildx + uses: crazy-max/ghaction-docker-buildx@v3 + with: + buildx-version: latest + qemu-version: latest + + - name: Available platforms + run: echo ${{ steps.buildx.outputs.platforms }} + + - name: Login to DockerHub + if: success() && github.event_name != 'pull_request' + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Building container + run: ./bin/build_containers.sh diff --git a/.gitignore b/.gitignore index e27ce00bb..38857cf77 100644 --- a/.gitignore +++ b/.gitignore @@ -36,5 +36,4 @@ pip-log.txt venv node_modules *.retry - .env diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e95c6a3a9..000000000 --- a/.travis.yml +++ /dev/null @@ -1,51 +0,0 @@ -language: python -python: - - "2.7" -virtualenv: - system_site_packages: true -addons: - firefox: "45.0" - apt: - update: true - packages: - - net-tools - - mplayer - - ffmpeg - - python-gobject - - python-setuptools -install: - - pip install -U pip - - pip install -r requirements/requirements.txt - - pip install -r requirements/requirements.dev.txt -before_script: - - mkdir -p ~/.screenly ~/.config/uzbl/ ~/screenly_assets /tmp/USB/cleanup_folder - - cp ansible/roles/screenly/files/uzbl-config ~/.config/uzbl/config-screenly - - cp ansible/roles/screenly/files/screenly.conf ~/.screenly/ - - cp ansible/roles/screenly/files/screenly.db ~/.screenly/ - - sudo cp bin/install.sh /usr/local/sbin/upgrade_screenly.sh - - sudo chmod 0700 /usr/local/sbin/upgrade_screenly.sh - - echo -e "[local]\nlocalhost ansible_connection=local" > ansible/localhost - - curl https://www.screenly.io/upload/ose-logo.png > /tmp/image.png - - cp /tmp/image.png /tmp/USB/image.png - - cp /tmp/image.png /tmp/USB/cleanup_folder/image.png - - curl https://www.screenly.io/upload/ose-logo.png > ~/screenly_assets/image.tmp - - curl https://www.screenly.io/upload/big_buck_bunny_720p_10mb.flv > /tmp/video.flv - - cp tests/assets/asset.mov /tmp/asset.mov - - export DISPLAY=:99.0 - - /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 - - sudo cp tests/config/ffserver.conf /etc/ffserver.conf - - /usr/bin/ffserver -f /etc/ffserver.conf & - - sleep 3 - - python server.py & - - sleep 3 # give xvfb some time to start - -script: - - find . ! -path "*/rtmplite/*" -name \*.py -exec pep8 --ignore=E402,E501,E731 {} + - - nosetests -v -a '!fixme' - - ansible-playbook --syntax-check -i ansible/localhost ansible/site.yml - - python -m SimpleHTTPServer 8081 & - - sleep 3 - - bash static/spec/runner.sh - -sudo: false -dist: xenial diff --git a/README.md b/README.md index ff38e7147..7287f9a4f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ [](https://travis-ci.org/Screenly/screenly-ose) [](https://www.codacy.com/app/vpetersson/screenly-ose?utm_source=github.com&utm_medium=referral&utm_content=Screenly/screenly-ose&utm_campaign=Badge_Grade) +[](https://dashboard.balena-cloud.com/deploy?repoUrl=https://github.com/screenly/screenly-ose&defaultDeviceType=raspberrypi3) # Screenly OSE - Digital Signage for the Raspberry Pi @@ -9,12 +10,6 @@ Want to help OSE thrive? Support us using [GitHub Sponsor](https://github.com/sponsors/Screenly). -## A note on Raspberry Pi 4 support - -Screenly OSE does not currently support the Raspberry Pi 4 Model B (well). We are looking for volunteers to help us with this. The remaining work is tracked [here](https://github.com/Screenly/screenly-ose/milestone/12). In short, we are doing a big overhaul (moving to Docker and QT/QTWebEngine). This will allow us to get things like a modern browser with hardware acceleration, as well as a simpler installation process. - -If you got experience with QT, we'd love your help. - ## Disk images The recommended installation method is to grab the latest disk image from [here](https://github.com/Screenly/screenly-ose/releases). diff --git a/ansible/roles/network/tasks/main.yml b/ansible/roles/network/tasks/main.yml index 5847349eb..294befbd9 100644 --- a/ansible/roles/network/tasks/main.yml +++ b/ansible/roles/network/tasks/main.yml @@ -13,7 +13,7 @@ command: systemctl disable screenly-net-watchdog.timer when: screenly_network_manager_exist -- name: Remove network manger and watchdog +- name: Remove network manager and watchdog file: state: absent path: "/usr/sbin/{{ item }}" @@ -70,91 +70,3 @@ when: - ansible_distribution_major_version|int >= 9 - manage_network|bool == true - -- name: Check if resin-wifi-connect required version exist - stat: - path: "/usr/local/share/wifi-connect/ui/{{ resin_wifi_connect_version }}" - register: resin_wifi_version_file - when: - - ansible_distribution_major_version|int >= 9 - -- set_fact: resin_wifi_version_file_exist="{{resin_wifi_version_file.stat.exists}}" - when: - - ansible_distribution_major_version|int >= 9 - -- name: Download resin-wifi-connect release - get_url: - url: "https://github.com/resin-io/resin-wifi-connect/releases/download/v{{ resin_wifi_connect_version }}/wifi-connect-v{{ resin_wifi_connect_version }}-linux-rpi.tar.gz" - dest: /home/pi/resin-wifi-connect.tar.gz - when: - - ansible_distribution_major_version|int >= 9 - - not resin_wifi_version_file_exist - - manage_network|bool == true - -- name: Unarchive resin-wifi-connect release - unarchive: - src: /home/pi/resin-wifi-connect.tar.gz - dest: /home/pi - owner: pi - group: pi - when: - - ansible_distribution_major_version|int >= 9 - - not resin_wifi_version_file_exist - - manage_network|bool == true - -- name: Copy "ui" folder - copy: - src: /home/pi/ui/ - dest: /usr/local/share/wifi-connect/ui - mode: 0755 - when: - - ansible_distribution_major_version|int >= 9 - - not resin_wifi_version_file_exist - - manage_network|bool == true - -- name: Copy wifi-connect file - copy: - src: /home/pi/wifi-connect - dest: /usr/local/sbin - mode: 0755 - when: - - ansible_distribution_major_version|int >= 9 - - not resin_wifi_version_file_exist - - manage_network|bool == true - -- name: Touch resin-wifi-connect version file - file: - state: touch - path: "/usr/local/share/wifi-connect/ui/{{ resin_wifi_connect_version }}" - when: - - ansible_distribution_major_version|int >= 9 - - not resin_wifi_version_file_exist - - manage_network|bool == true - -- name: Remove unarchive files - file: - state: absent - path: "/home/pi/{{ item }}" - with_items: - - wifi-connect - - ui - - resin-wifi-connect.tar.gz - when: - - ansible_distribution_major_version|int >= 9 - - not resin_wifi_version_file_exist - - manage_network|bool == true - -- name: Copy wifi-connect systemd unit - copy: - src: "wifi-connect.service" - dest: "/etc/systemd/system/wifi-connect.service" - -- name: Enable wifi-connect systemd service - systemd: - name: wifi-connect.service - enabled: yes - -- name: Touch initialized file - file: - state: touch - path: "/home/pi/.screenly/initialized" diff --git a/ansible/roles/network/vars/main.yml b/ansible/roles/network/vars/main.yml index 3709d64ab..22ae95f98 100644 --- a/ansible/roles/network/vars/main.yml +++ b/ansible/roles/network/vars/main.yml @@ -1 +1 @@ -resin_wifi_connect_version: 4.2.13 +balena_wifi_connect_version: 4.2.13 diff --git a/ansible/roles/nginx/files/nginx.conf b/ansible/roles/nginx/files/nginx.conf deleted file mode 100644 index e17977dc7..000000000 --- a/ansible/roles/nginx/files/nginx.conf +++ /dev/null @@ -1,53 +0,0 @@ -upstream ose { - server 127.0.0.1:8080; -} - -upstream wifi-connect { - server 192.168.42.1:9090; -} - -server { - server_tokens off; - listen 80 default_server; - - location / { - if (-f /home/pi/.screenly/initialized) { - proxy_pass http://ose; - } - if (!-f /home/pi/.screenly/initialized) { - proxy_pass http://wifi-connect; - } - - client_max_body_size 4G; - 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; - } - - location ~ ^/api/[0-9a-z]+/backup$ { - proxy_pass http://ose; - proxy_connect_timeout 1800; - proxy_send_timeout 1800; - proxy_read_timeout 1800; - send_timeout 1800; - - client_max_body_size 4G; - 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; - } - - location /static { - proxy_pass http://ose/static; - } - - location /hotspot { - allow 127.0.0.1; - deny all; - - if (!-f /home/pi/.screenly/initialized) { - root /tmp; - rewrite ^ /hotspot.html break; - } - } -} diff --git a/ansible/roles/nginx/tasks/main.yml b/ansible/roles/nginx/tasks/main.yml deleted file mode 100644 index dc2561c97..000000000 --- a/ansible/roles/nginx/tasks/main.yml +++ /dev/null @@ -1,33 +0,0 @@ ---- -# Enable Nginx -- name: Check screenly.conf - command: cat /home/pi/.screenly/screenly.conf - register: config - -- set_fact: no_ssl="{{config.stdout.find('use_ssl = True') == -1}}" - -- name: Installs Nginx - apt: - name: nginx-light - state: present - update_cache: yes - -- name: Cleans up default config - file: - path: /etc/nginx/sites-enabled/default - state: absent - -- name: Installs nginx config - copy: - src: nginx.conf - dest: /etc/nginx/sites-enabled/screenly.conf - mode: 644 - owner: root - group: root - -- name: Modifies screenly-web service to only listen on localhost - lineinfile: - regexp: '^.*LISTEN.*' - state: absent - dest: /etc/systemd/system/screenly-web.service - when: no_ssl diff --git a/ansible/roles/rpi-update/tasks/main.yml b/ansible/roles/rpi-update/tasks/main.yml deleted file mode 100644 index b8092e0cb..000000000 --- a/ansible/roles/rpi-update/tasks/main.yml +++ /dev/null @@ -1,24 +0,0 @@ ---- - -- name: Download rpi-update - get_url: - url: https://raw.githubusercontent.com/Hexxeh/rpi-update/master/rpi-update - dest: /usr/bin/rpi-update - mode: 0755 - owner: root - group: root - when: ansible_distribution_release == "wheezy" - -- name: Run kernel upgrade (this can take up to 10 minutes) - command: /usr/bin/rpi-update - when: ansible_distribution_release == "wheezy" - environment: - SKIP_WARNING: 1 - register: rpiupdate - tags: - - system-upgrade - -- debug: msg="{{ rpiupdate.stdout }}" - when: ansible_distribution_release == "wheezy" - tags: - - system-upgrade diff --git a/ansible/roles/screenly/files/X.service b/ansible/roles/screenly/files/X.service deleted file mode 100644 index b59dfee83..000000000 --- a/ansible/roles/screenly/files/X.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=X11 -After=network.target - -[Service] -ExecStart=/usr/bin/X -User=root -Restart=on-failure - -[Install] -WantedBy=multi-user.target \ No newline at end of file diff --git a/ansible/roles/screenly/files/gtkrc-2.0 b/ansible/roles/screenly/files/gtkrc-2.0 deleted file mode 100644 index 8d399f94f..000000000 --- a/ansible/roles/screenly/files/gtkrc-2.0 +++ /dev/null @@ -1,9 +0,0 @@ -style "uzbl" { - GtkScrollbar::slider-width=0 - GtkScrollbar::trough-border=0 - GtkScrollbar::has-backward-stepper=0 - GtkScrollbar::has-forward-stepper=0 - GtkScrollbar::has-secondary-backward-stepper=0 - GtkScrollbar::has-secondary-forward-stepper=0 -} -widget "Uzbl*" style "uzbl" diff --git a/ansible/roles/screenly/files/matchbox.service b/ansible/roles/screenly/files/matchbox.service deleted file mode 100644 index 6bb0b06df..000000000 --- a/ansible/roles/screenly/files/matchbox.service +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=X11 -After=X.service - -[Service] -Environment=DISPLAY=:0.0 -ExecStart=/usr/bin/matchbox-window-manager -use_titlebar no -use_cursor no -User=pi -Restart=on-failure - -[Install] -WantedBy=multi-user.target diff --git a/ansible/roles/screenly/files/plymouth-quit-wait.service b/ansible/roles/screenly/files/plymouth-quit-wait.service deleted file mode 100755 index 9099edc41..000000000 --- a/ansible/roles/screenly/files/plymouth-quit-wait.service +++ /dev/null @@ -1,8 +0,0 @@ -[Unit] -Description=Hold until boot process finishes up -After=rc-local.service plymouth-start.service systemd-user-sessions.service screenly-viewer.service - -[Service] -ExecStart=-/bin/plymouth --wait -Type=oneshot -TimeoutSec=0 diff --git a/ansible/roles/screenly/files/plymouth-quit.service b/ansible/roles/screenly/files/plymouth-quit.service deleted file mode 100755 index b24cf2012..000000000 --- a/ansible/roles/screenly/files/plymouth-quit.service +++ /dev/null @@ -1,8 +0,0 @@ -[Unit] -Description=Terminate Plymouth Boot Screen -After=rc-local.service plymouth-start.service systemd-user-sessions.service screenly-viewer.service - -[Service] -ExecStart=-/bin/plymouth quit -Type=oneshot -TimeoutSec=20 diff --git a/ansible/roles/screenly/files/screenly-celery.service b/ansible/roles/screenly/files/screenly-celery.service deleted file mode 100644 index 82b5ebe63..000000000 --- a/ansible/roles/screenly/files/screenly-celery.service +++ /dev/null @@ -1,13 +0,0 @@ -[Unit] -Description=Screenly celery worker -After=redis-server.service - -[Service] -WorkingDirectory=/home/pi/screenly -User=pi -ExecStart=/usr/local/bin/celery worker -A server.celery -B -n worker@screenly --loglevel=info --schedule /home/pi/.screenly/celerybeat-schedule -Restart=always -RestartSec=5 - -[Install] -WantedBy=multi-user.target diff --git a/ansible/roles/screenly/files/screenly-viewer.service b/ansible/roles/screenly/files/screenly-viewer.service deleted file mode 100644 index e606d80b2..000000000 --- a/ansible/roles/screenly/files/screenly-viewer.service +++ /dev/null @@ -1,32 +0,0 @@ -[Unit] -Description=Screenly Viewer -After=matchbox.service screenly-web.service - -[Service] -WorkingDirectory=/home/pi/screenly -User=pi - -Environment=DISPLAY=:0.0 - -# Fix white flickering in omxplayer -Environment=NOREFRESH=1 - -Environment=PYTHONPATH=/home/pi/screenly - -# Don't activate screensaver -ExecStartPre=/usr/bin/xset s off - -# Disable DPMS (Energy Star) features -ExecStartPre=/usr/bin/xset -dpms - -# Don't blank the video device -ExecStartPre=/usr/bin/xset s noblank - -ExecStart=/usr/bin/python /home/pi/screenly/viewer.py -Restart=on-failure - -ExecStartPost=/bin/rm -f /tmp/uzbl_* -ExecStartPost=/bin/rm -f /tmp/screenly_html/* - -[Install] -WantedBy=multi-user.target diff --git a/ansible/roles/screenly/files/screenly-web.service b/ansible/roles/screenly/files/screenly-web.service deleted file mode 100644 index 15051195c..000000000 --- a/ansible/roles/screenly/files/screenly-web.service +++ /dev/null @@ -1,15 +0,0 @@ -[Unit] -Description=Screenly Web UI -After=network-online.target - -[Service] -WorkingDirectory=/home/pi/screenly -User=pi -ExecStartPre=/usr/bin/python /home/pi/screenly/bin/wait.py -ExecStart=/usr/bin/python /home/pi/screenly/server.py -Restart=always -RestartSec=5 -Environment=PYTHONPATH=/home/pi/screenly - -[Install] -WantedBy=multi-user.target diff --git a/ansible/roles/screenly/files/screenly-websocket_server_layer.service b/ansible/roles/screenly/files/screenly-websocket_server_layer.service deleted file mode 100644 index e196768c0..000000000 --- a/ansible/roles/screenly/files/screenly-websocket_server_layer.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Websocket Server layer - -[Service] -WorkingDirectory=/home/pi/screenly -User=pi -ExecStart=/usr/bin/python /home/pi/screenly/websocket_server_layer.py -Restart=always - -[Install] -WantedBy=multi-user.target \ No newline at end of file diff --git a/ansible/roles/screenly/files/uzbl-config b/ansible/roles/screenly/files/uzbl-config deleted file mode 100644 index 74a3fa5c5..000000000 --- a/ansible/roles/screenly/files/uzbl-config +++ /dev/null @@ -1,5 +0,0 @@ -set show_status = 0 -set on_event = request ON_EVENT - -@on_event LOAD_START js alert=function(e){return true};confirm=function(e){return true};prompt=function(e){return true}; -@on_event LOAD_COMMIT js alert=function(e){return true};confirm=function(e){return true};prompt=function(e){return true}; diff --git a/ansible/roles/screenly/tasks/main.yml b/ansible/roles/screenly/tasks/main.yml index 33eaa68e0..1feca09e3 100644 --- a/ansible/roles/screenly/tasks/main.yml +++ b/ansible/roles/screenly/tasks/main.yml @@ -7,15 +7,7 @@ with_items: - .screenly - .config - - .config/uzbl - -- name: Copy Screenly default config - copy: - owner: pi - group: pi - src: screenly.conf - dest: /home/pi/.screenly/screenly.conf - force: no + - screenly_assets - name: Copy Screenly default assets file copy: @@ -31,40 +23,11 @@ state: absent dest: /home/pi/.screenly/screenly.conf -- name: Copy in GTK config - copy: - owner: pi - group: pi - src: gtkrc-2.0 - dest: /home/pi/.gtkrc-2.0 - -- name: Copy in UZBL config - copy: - owner: pi - group: pi - src: uzbl-config - dest: /home/pi/.config/uzbl/config-screenly - - name: Install pip dependencies pip: - requirements: /home/pi/screenly/requirements/requirements.txt + requirements: /home/pi/screenly/requirements/requirements.host.txt extra_args: "--no-cache-dir --upgrade" -- name: Create default assets database if does not exists - copy: - owner: pi - group: pi - src: screenly.db - dest: /home/pi/.screenly/screenly.db - force: no - -- name: Run database migration - become_user: pi - command: python /home/pi/screenly/bin/migrate.py - register: migrate - -- debug: msg="{{ migrate.stdout }}" - - name: Remove screenly_utils.sh file: state: absent @@ -125,22 +88,37 @@ dest: "/etc/systemd/system/{{ item }}" with_items: "{{ screenly_systemd_units }}" -- name: Copy plymouth-quit-wait.service - copy: - src: plymouth-quit-wait.service +- name: Remove plymouth-quit-wait.service + file: + state: absent dest: /lib/systemd/system/plymouth-quit-wait.service - mode: 0644 - owner: root - group: root -- name: Copy plymouth-quit.service - copy: - src: plymouth-quit.service +- name: Remove plymouth-quit.service + file: + state: absent dest: /lib/systemd/system/plymouth-quit.service - mode: 0644 - owner: root - group: root - name: Enable screenly systemd services command: systemctl enable {{ item }} chdir=/etc/systemd/system with_items: "{{ screenly_systemd_units }}" + +- name: Check if deprecated systemd services exists + stat: + path: /etc/systemd/system/X.service + register: x_service + +- set_fact: x_service_exist="{{x_service.stat.exists}}" + +- name: Disable deprecated systemd services + systemd: + name: "{{ item }}" + state: stopped + enabled: no + with_items: "{{ deprecated_screenly_systemd_units }}" + when: x_service_exist + +- name: Remove deprecated systemd units + file: + path: "/etc/systemd/system/{{ item }}" + state: absent + with_items: "{{ deprecated_screenly_systemd_units }}" diff --git a/ansible/roles/screenly/vars/main.yml b/ansible/roles/screenly/vars/main.yml index aa9688ad5..95a1aefc9 100644 --- a/ansible/roles/screenly/vars/main.yml +++ b/ansible/roles/screenly/vars/main.yml @@ -1,8 +1,11 @@ screenly_systemd_units: - - X.service - - matchbox.service + - udev-restart.service + +deprecated_screenly_systemd_units: - screenly-celery.service - - screenly-viewer.service - screenly-web.service - screenly-websocket_server_layer.service - - udev-restart.service + - screenly-viewer.service + - X.service + - matchbox.service + - wifi-connect.service diff --git a/ansible/roles/ssl/files/nginx.conf b/ansible/roles/ssl/files/nginx.conf deleted file mode 100644 index 0f8a23a0a..000000000 --- a/ansible/roles/ssl/files/nginx.conf +++ /dev/null @@ -1,84 +0,0 @@ -upstream ose { - server 127.0.0.1:8080; -} - -upstream websocket { - server 127.0.0.1:9999; -} - -upstream wifi-connect { - server 192.168.42.1:9090; -} - -server { - server_tokens off; - listen 80 default_server; - - location / { - return 301 https://$host$request_uri; - } -} - -server { - server_tokens off; - listen 443 default_server; - - ssl on; - ssl_certificate /etc/ssl/screenly.crt; - ssl_certificate_key /etc/ssl/screenly.key; - - location / { - if (-f /home/pi/.screenly/initialized) { - proxy_pass http://ose; - } - if (!-f /home/pi/.screenly/initialized) { - proxy_pass http://wifi-connect; - } - - client_max_body_size 4G; - 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-Forwarded-Protocol https; - } - - location ~ ^/api/[0-9a-z]+/backup$ { - proxy_pass http://ose; - proxy_connect_timeout 1800; - proxy_send_timeout 1800; - proxy_read_timeout 1800; - send_timeout 1800; - - client_max_body_size 4G; - 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-Forwarded-Protocol https; - } - - location /static { - proxy_pass http://ose/static; - } - - location /ws/ { - proxy_pass http://websocket; - proxy_read_timeout 24d; - chunked_transfer_encoding off; - proxy_http_version 1.1; - proxy_buffering off; - - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $http_host; - } - - location /hotspot { - allow 127.0.0.1; - deny all; - - if (!-f /home/pi/.screenly/initialized) { - root /tmp; - rewrite ^ /hotspot.html break; - } - } -} diff --git a/ansible/roles/ssl/files/nginx_resin.conf b/ansible/roles/ssl/files/nginx_resin.conf deleted file mode 100644 index 5f7577315..000000000 --- a/ansible/roles/ssl/files/nginx_resin.conf +++ /dev/null @@ -1,47 +0,0 @@ -upstream ose { - server 127.0.0.1:8080; -} - -upstream websocket { - server 127.0.0.1:9999; -} - -server { - server_tokens off; - listen 80 default_server; - - location / { - client_max_body_size 4G; - proxy_pass http://ose; - 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-Forwarded-Protocol https; - } - - location ~ ^/api/[0-9a-z]+/backup$ { - proxy_pass http://ose; - proxy_connect_timeout 1800; - proxy_send_timeout 1800; - proxy_read_timeout 1800; - send_timeout 1800; - - client_max_body_size 4G; - 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-Forwarded-Protocol https; - } - - location /ws/ { - proxy_pass http://websocket; - proxy_read_timeout 24d; - chunked_transfer_encoding off; - proxy_http_version 1.1; - proxy_buffering off; - - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $http_host; - } -} diff --git a/ansible/roles/ssl/files/screenly.crt b/ansible/roles/ssl/files/screenly.crt deleted file mode 100644 index 34f03cea9..000000000 --- a/ansible/roles/ssl/files/screenly.crt +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIJAN+OcHLBe0iHMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV -BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQKDAxXaXJlTG9hZCBJ -bmMxFzAVBgNVBAMMDnNjcmVlbmx5LmxvY2FsMB4XDTE4MDIyODA4MzUyM1oXDTI4 -MDIyODA4MzUyM1owUjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx -FTATBgNVBAoMDFdpcmVMb2FkIEluYzEXMBUGA1UEAwwOc2NyZWVubHkubG9jYWww -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPPVMqJTLiKw4+uSOS72/Y -ZgxOaajHPRt47oSHqkHEfvDfIULSqsX4LJkQroP85bK9EmwmWZ5INUNbwy364xHK -M2i6p9fv8nG1wAYa1thhWian5VN9VV4jf8zdM3uYYKwYUg+hlXxJlgQVMVUQ8Sdq -oPLG/0/Qmk4cSXHq3vlT/NDzQVUQZn8BNTZ5oTpASbEotzHpf3+lF77V6ql88ytO -9r/ds2vZ8oOWQ0TiugP/cKwImYExTT8GGWeX9H6zMInbfAO3MhmwmXmymeDy6VZD -a5uDKxbD9ui4zRDQRsTolagy17FkjIm8kkPfDdhVxDJtvnrgXzWF/IjRloPsykDJ -AgMBAAGjUDBOMB0GA1UdDgQWBBSSz3mZLOfI0l+jv8JsKAU9n6SFFDAfBgNVHSME -GDAWgBSSz3mZLOfI0l+jv8JsKAU9n6SFFDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3 -DQEBCwUAA4IBAQA3g/JCy9JNPCODy9CNIDEFWLPyPzrAoxZOSQPVsvFZr6h5En4N -KBrTGaeoPRYRLqQOAIq6D4a4bV0JgEiFMTd93XIglbt6KHkqLFPAnb96JNrbqsLx -7ESgvFN03TovqT2u7M3uj/qjeWG6ZP8Py36jjuwaBwkvp4HdirxsPSYH+sJluFr4 -QgUYnVZPWJYGQE3nHuAT+LJ7EjVVJj0QWcjIR/l3ckgnACinXc0Mik4Fheh1gAgI -k2cK6HBGveFuekbOdu35o5zFvTt0L3wPQzd+VkuPfkfv1iF9YqeiJOvW8W/PH9z3 -VW/psItcnkU4bH2asTEL8ryC/+0x7xoAUlys ------END CERTIFICATE----- diff --git a/ansible/roles/ssl/files/screenly.key b/ansible/roles/ssl/files/screenly.key deleted file mode 100644 index a5bacd21f..000000000 --- a/ansible/roles/ssl/files/screenly.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDPPVMqJTLiKw4+ -uSOS72/YZgxOaajHPRt47oSHqkHEfvDfIULSqsX4LJkQroP85bK9EmwmWZ5INUNb -wy364xHKM2i6p9fv8nG1wAYa1thhWian5VN9VV4jf8zdM3uYYKwYUg+hlXxJlgQV -MVUQ8SdqoPLG/0/Qmk4cSXHq3vlT/NDzQVUQZn8BNTZ5oTpASbEotzHpf3+lF77V -6ql88ytO9r/ds2vZ8oOWQ0TiugP/cKwImYExTT8GGWeX9H6zMInbfAO3MhmwmXmy -meDy6VZDa5uDKxbD9ui4zRDQRsTolagy17FkjIm8kkPfDdhVxDJtvnrgXzWF/IjR -loPsykDJAgMBAAECggEAS93vbCZiElogxOWSGGB/WYFCUBJuL0I3pHXtHp09pmmy -VH0gsW7DOq9Y+bppp1OPs5fi78cvItAc8KLrWkV2ZcecN3jqnHTtG9RIZ9rvK/SM -4joZ7nAqHmTS4sfOH2KEngKspkLLVUUOCZQdyC4AeBCj0CX3Wi6jGcfpZEpsjEoA -pbp1HhgJTs6GNdOKcGWYaTJt1lj5/MFdOgwX4F9gGMv9YD7+0ORBL+pflNA5F7YO -QIprGYU43Q3i2iBofImkl0TmKS6zL8inrcQ6YNY+jxZjc1YyC+C3cv0qFmIx0uu5 -/psoin3IgruFfv0Oq4VOvA7p6TLFhVLt0Jr/V3ZMAQKBgQDrSOhHaN9rHEm2QCBA -gdV9dmaYAfJMIAERSEb/Dwsb18tNR9Ft5vXixED3QG1GqhQdMWBCoQ9vDuYKjmSx -4wozdrh3IX0EyRAhxagi9QYlWbg6yHHtWdk+XaTGiVHQDh9gPFbJaqbok6aArqdk -xR3jD3EFNYf+r6CVsHaUDBRs8QKBgQDhfE4C5Jd5OyMabUy7N5T45SkA7Yof6S6k -uYBOMOF7iBz0obOQr/HvkJV468xgt3OKwiHRAJL6XbvFxrBLhcbkFZ4aTksEBNwm -brzm03S9RrE3ezJRbVSEgFNt1c6Km9UmpZxm2U6B05n7wdRWR590/5N6XG24gDlu -GReSdzpxWQKBgQCoLMi6oh9v9BxMBLII6cSrlQHoDRwfhZC9xafZj+skz64lYvwz -Ti7bE+RL1uVE6TTPWQexGGZrv352dSlMbThRaL6ZiHpP/VdmjF2N/w2RjPu+KKAm -Q16g0VaCAo1T5YRPyVFPTshW3ZLZz/0ebjbaoaLrUkQOq4Jg/G0FjUzcQQKBgQDd -4h46Botvxluyo5+AEx/LFGWW/iiPYjx95/Rz/PHFR5mGuKAkXp6qaRJNHWvOOHfA -MWxpaDE5oYcnBW9xwcCHrSYZKLX0zHt+bjYAxk/3+VpmCBrpubYTdNukF2LZTqMf -FpSjOG9incDG1mOGS5CD5wNOwylNBxB8YMCrZhvicQKBgCcfK/hRQazPW9EZlP9t -pkv9Aujwql9gqAwI2EDe4/aesUn5TWvd8PvPoymbTguHNdQq8AoB/IUEhYpNVPCc -AsRgJUSU//G0D7swhLy7zdXQt2EdE+3V8riAayPia4LefUpVEQG0szoS+UFdorxM -BMvXYWZxzHAvp0KUr3G9S+dr ------END PRIVATE KEY----- diff --git a/ansible/roles/ssl/tasks/main.yml b/ansible/roles/ssl/tasks/main.yml deleted file mode 100644 index ace2021f0..000000000 --- a/ansible/roles/ssl/tasks/main.yml +++ /dev/null @@ -1,82 +0,0 @@ ---- -- name: Check screenly.conf - command: cat /home/pi/.screenly/screenly.conf - register: config - tags: - - enable-ssl - -- set_fact: no_use_ssl_parameter="{{config.stdout.find('use_ssl') == -1}}" - tags: - - enable-ssl - -- name: Installs Nginx - apt: - name: nginx-light - state: present - update_cache: yes - tags: - - enable-ssl - -- name: Cleans up default config - file: - path: /etc/nginx/sites-enabled/default - state: absent - tags: - - enable-ssl - -- name: Installs nginx config - copy: - src: nginx.conf - dest: /etc/nginx/sites-enabled/screenly.conf - mode: 644 - owner: root - group: root - notify: - - restart-nginx - tags: - - enable-ssl - -- name: Installs self-signed certificates - copy: - src: "{{ item }}" - dest: "/etc/ssl/{{ item }}" - mode: 0600 - owner: root - group: root - force: no - with_items: - - screenly.crt - - screenly.key - tags: - - enable-ssl - -- name: Turn on the ssl mode - lineinfile: - dest: /home/pi/.screenly/screenly.conf - insertafter: '^.*database.*' - regexp: '^.*database.*;' - line: 'use_ssl = True' - tags: - - enable-ssl - when: no_use_ssl_parameter - -- name: Turns on the ssl mode - replace: - replace: 'use_ssl = True' - regexp: '^.*use_ssl.*' - dest: /home/pi/.screenly/screenly.conf - tags: - - enable-ssl - when: not no_use_ssl_parameter - -- name: Modifies screenly-web service to only listen on localhost - lineinfile: - regexp: '^.*LISTEN.*' - state: absent - dest: /etc/systemd/system/screenly-web.service - notify: - - reload systemctl - - restart-screenly-websocket_server_layer - - restart-screenly-server - tags: - - enable-ssl diff --git a/ansible/roles/system/files/10-evdev.conf b/ansible/roles/system/files/10-evdev.conf deleted file mode 100644 index ba37ec34d..000000000 --- a/ansible/roles/system/files/10-evdev.conf +++ /dev/null @@ -1,40 +0,0 @@ -# -# Catch-all evdev loader for udev-based systems -# We don't simply match on any device since that also adds accelerometers -# and other devices that we don't really want to use. The list below -# matches everything but joysticks. - -#Section "InputClass" -# Identifier "evdev pointer catchall" -# MatchIsPointer "on" -# MatchDevicePath "/dev/input/event*" -# Driver "evdev" -#EndSection - -Section "InputClass" - Identifier "evdev keyboard catchall" - MatchIsKeyboard "on" - MatchDevicePath "/dev/input/event*" - Driver "evdev" -EndSection - -#Section "InputClass" -# Identifier "evdev touchpad catchall" -# MatchIsTouchpad "on" -# MatchDevicePath "/dev/input/event*" -# Driver "evdev" -#EndSection - -#Section "InputClass" -# Identifier "evdev tablet catchall" -# MatchIsTablet "on" -# MatchDevicePath "/dev/input/event*" -# Driver "evdev" -#EndSection - -#Section "InputClass" -# Identifier "evdev touchscreen catchall" -# MatchIsTouchscreen "on" -# MatchDevicePath "/dev/input/event*" -# Driver "evdev" -#EndSection diff --git a/ansible/roles/system/files/10-serverflags.conf b/ansible/roles/system/files/10-serverflags.conf deleted file mode 100644 index c7c69374a..000000000 --- a/ansible/roles/system/files/10-serverflags.conf +++ /dev/null @@ -1,6 +0,0 @@ -Section "ServerFlags" - Option "BlankTime" "0" - Option "StandbyTime" "0" - Option "SuspendTime" "0" - Option "OffTime" "0" -EndSection diff --git a/ansible/roles/system/files/rc.local b/ansible/roles/system/files/rc.local index f9deddba7..732ee60ce 100644 --- a/ansible/roles/system/files/rc.local +++ b/ansible/roles/system/files/rc.local @@ -3,6 +3,9 @@ # Make sure the SSH host keys have been generated ssh-keygen -A +# Solves issue with black square in the upper left-hand corner +/bin/chvt 8 ; sleep 0.1 ; /bin/chvt 7 + # Disable wifi power management if [ "$(ip address | grep wlan)" ]; then iwconfig wlan0 power off diff --git a/ansible/roles/system/tasks/main.yml b/ansible/roles/system/tasks/main.yml index efd72dca2..435cf9f39 100644 --- a/ansible/roles/system/tasks/main.yml +++ b/ansible/roles/system/tasks/main.yml @@ -44,6 +44,30 @@ tags: - touches_boot_partition +- name: Add gpu_mem_256 in config.txt if it doesn't exist + lineinfile: + path: /boot/config.txt + line: gpu_mem_256=96 + when: config_txt.stdout.find('gpu_mem_256') == -1 + tags: + - touches_boot_partition + +- name: Add gpu_mem_512 in config.txt if it doesn't exist + lineinfile: + path: /boot/config.txt + line: gpu_mem_512=128 + when: config_txt.stdout.find('gpu_mem_512') == -1 + tags: + - touches_boot_partition + +- name: Add gpu_mem_1024 in config.txt if it doesn't exist + lineinfile: + path: /boot/config.txt + line: gpu_mem_1024=196 + when: config_txt.stdout.find('gpu_mem_1024') == -1 + tags: + - touches_boot_partition + - name: Backup kernel boot args copy: src: /boot/cmdline.txt @@ -154,49 +178,64 @@ - name: Install Screenly dependencies apt: name: - - console-data - - libffi-dev - - libssl-dev - - matchbox - - omxplayer - - python-dev - - python-gobject - - python-netifaces - - python-simplejson - - redis-server - rpi-update - - sqlite3 - - systemd - - uzbl - - x11-xserver-utils - - xserver-xorg state: latest -- name: Install systemd-sysv on Wheezy - command: bash -c 'echo "Yes, do as I say!" | apt-get install -y --force-yes systemd-sysv' - when: ansible_distribution_release == "wheezy" - - name: Remove deprecated apt dependencies apt: name: - - supervisor + - dphys-swapfile - lightdm - lightdm-gtk-greeter - - dphys-swapfile - - rabbitmq-server + - matchbox + - nginx-common + - nginx-light - pix-plym-splash + - rabbitmq-server + - redis-server + - supervisor + - uzbl + - x11-xserver-utils + - xserver-xorg state: absent - -- name: Remove cups/printing related packages + +- name: Add docker apt key + apt_key: + url: https://download.docker.com/linux/raspbian/gpg + state: present + +- name : Get raspbian name + command: lsb_release -cs + register: raspbian_name + +- name: Add Docker repo + lineinfile: + path: /etc/apt/sources.list.d/docker.list + create: yes + line: "deb [arch=armhf] https://download.docker.com/linux/raspbian {{ raspbian_name.stdout }} edge" + state: present + +- name: Install Docker apt: - name: - - cups - - cups-browsed - - cups-client - - cups-common - - cups-daemon - - cups-server-common - state: absent + name: docker-ce + update_cache: yes + install_recommends: no + +- name: Add pi to docker group + user: + name: pi + group: pi + groups: + - docker + - adm + - sudo + - video + - plugdev + - users + - input + - netdev + - gpio + - dialout - name: Perform system upgrade apt: @@ -231,31 +270,6 @@ owner: root group: root -- name: Copy in evdev - copy: - src: 10-evdev.conf - dest: /usr/share/X11/xorg.conf.d/10-evdev.conf - mode: 0644 - owner: root - group: root - -- name: Disable DPMS - copy: - src: 10-serverflags.conf - dest: /usr/share/X11/xorg.conf.d/10-serverflags.conf - mode: 0644 - owner: root - group: root - -- name: Clear out X11 configs (disables touchpad and other unnecessary things) - file: - path: "/usr/share/X11/xorg.conf.d/{{ item }}" - state: absent - with_items: - - 50-synaptics.conf - - 10-quirks.conf - - 50-wacom.conf - - name: Disable swap command: /sbin/swapoff --all removes=/var/swap diff --git a/ansible/roles/tools/files/nginx.conf b/ansible/roles/tools/files/nginx.conf deleted file mode 100644 index 1452c6f2f..000000000 --- a/ansible/roles/tools/files/nginx.conf +++ /dev/null @@ -1,6 +0,0 @@ -server { - listen 127.0.0.1:8000; - server_name *.ngrok.io; - root /home/pi/screenly_assets; - try_files $uri /home/pi/screenly_assets$uri; -} diff --git a/ansible/roles/tools/tasks/main.yml b/ansible/roles/tools/tasks/main.yml index c9bb17de8..115b58c95 100644 --- a/ansible/roles/tools/tasks/main.yml +++ b/ansible/roles/tools/tasks/main.yml @@ -5,11 +5,3 @@ mode: 0755 owner: root group: root - -- name: Installs nginx config - copy: - src: nginx.conf - dest: /etc/nginx/sites-enabled/screenly_assets.conf - mode: 644 - owner: root - group: root diff --git a/ansible/site.yml b/ansible/site.yml index d16b68967..e5c7b0024 100644 --- a/ansible/site.yml +++ b/ansible/site.yml @@ -4,37 +4,12 @@ become: yes vars: manage_network: "{{ lookup('env', 'MANAGE_NETWORK') }}" - - handlers: - - name: restart-nginx - service: - name: nginx - state: restarted - - - name: reload systemctl - command: systemctl daemon-reload - - - name: restart-screenly-websocket_server_layer - command: systemctl restart screenly-websocket_server_layer.service - - - name: restart-screenly-server - command: systemctl restart screenly-web.service - - - name: restart-x-server - command: "systemctl restart {{ item }}" - with_items: - - X.service - - matchbox.service - - - name: restart-screenly-viewer - command: systemctl restart screenly-viewer.service + docker_tag: "{{ lookup('env', 'DOCKER_TAG') }}" + device_type: "{{ lookup('env', 'DEVICE_TYPE') }}" roles: - system - - rpi-update - screenly - network - splashscreen - - nginx - - ssl - tools diff --git a/balena.yml b/balena.yml index f2917c79e..7fc2e23c1 100644 --- a/balena.yml +++ b/balena.yml @@ -10,12 +10,15 @@ assets: data: description: "Screenly OSE - Digital Signage for the Raspberry Pi" applicationConfigVariables: - - RESIN_HOST_CONFIG_gpu_mem: 128 - - RESIN_HOST_CONFIG_dtparam: "\"i2c_arm=on\",\"spi=on\",\"audio=on\",\"vc4-kms-v3d\"" + - BALENA_HOST_CONFIG_gpu_mem: 128 + - BALENA_HOST_CONFIG_framebuffer_depth: 32 + - BALENA_HOST_CONFIG_framebuffer_ignore_alpha: 1 + - BALENA_HOST_CONFIG_dtparam: "\"i2c_arm=on\",\"spi=on\",\"audio=on\",\"vc4-kms-v3d\"" defaultDeviceType: "raspberrypi3" supportedDeviceTypes: - "raspberry-pi" - "raspberry-pi2" - "raspberrypi3" - "raspberrypi3-64" + - "raspberrypi4-64" - "fincm3" diff --git a/bin/build_containers.sh b/bin/build_containers.sh new file mode 100755 index 000000000..bd3a4feb2 --- /dev/null +++ b/bin/build_containers.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# -*- sh-basic-offset: 4 -*- + +set -euo pipefail + +GITBRANCH=$(git rev-parse --abbrev-ref HEAD) + +if [ -n "${CROSS_COMPILE+x}" ]; then + echo "Running with cross-compile using docker buildx..." + DOCKER_BUILD_ARGS=("buildx" "build" "--push" "--platform" "linux/arm/v6,linux/arm/v7") +else + echo "Running without cross-compile..." + DOCKER_BUILD_ARGS=("build") +fi + +if [ -n "${CLEAN_BUILD+x}" ]; then + DOCKER_BUILD_ARGS+=("--no-cache") +fi + +for container in base server celery redis websocket nginx; do + echo "Building $container" + docker "${DOCKER_BUILD_ARGS[@]}" \ + -f "docker/Dockerfile.$container" \ + -t "screenly/srly-ose-$container:$GITBRANCH" . + + # Push if the push flag is set and not cross compiling + if [[ ( -n "${PUSH+x}" && -z "${CROSS_COMPILE+x}" ) ]]; then + docker push "screenly/srly-ose-$container:$GITBRANCH" + fi +done + +echo "Building viewer for different architectures..." +for pi_version in pi4 pi3 pi2 pi1; do + echo "Building viewer container for $pi_version" + docker "${DOCKER_BUILD_ARGS[@]}" \ + --build-arg "PI_VERSION=$pi_version" \ + -f docker/Dockerfile.viewer \ + -t "screenly/srly-ose-viewer:$GITBRANCH-$pi_version" . + + # Push if the push flag is set and not cross compiling + if [[ ( -n "${PUSH+x}" && -z "${CROSS_COMPILE+x}" ) ]]; then + docker push "screenly/srly-ose-viewer:$GITBRANCH-$pi_version" + fi +done + diff --git a/bin/install.sh b/bin/install.sh index a53c6ba5c..9c47b9986 100755 --- a/bin/install.sh +++ b/bin/install.sh @@ -36,7 +36,7 @@ if [ "$WEB_UPGRADE" = false ]; then # clear screen clear; - + # Set color of logo tput setaf 6 tput bold @@ -83,9 +83,7 @@ esac echo && read -p "Would you like to perform a full system upgrade as well? (y/N)" -n 1 -r -s UPGRADE && echo if [ "$UPGRADE" != 'y' ]; then - EXTRA_ARGS="--skip-tags enable-ssl,system-upgrade" - else - EXTRA_ARGS="--skip-tags enable-ssl" + EXTRA_ARGS=("--skip-tags" "system-upgrade") fi elif [ "$WEB_UPGRADE" = true ]; then @@ -94,7 +92,7 @@ elif [ "$WEB_UPGRADE" = true ]; then export DOCKER_TAG="latest" BRANCH="master" elif [ "$BRANCH_VERSION" = "production" ]; then - export DOCKER_TAG="production" + export DOCKER_TAG="latest" BRANCH="production" else echo -e "Invalid -b parameter." @@ -112,9 +110,7 @@ elif [ "$WEB_UPGRADE" = true ]; then fi if [ "$UPGRADE_SYSTEM" = false ]; then - EXTRA_ARGS="--skip-tags enable-ssl,system-upgrade" - elif [ "$UPGRADE_SYSTEM" = true ]; then - EXTRA_ARGS="--skip-tags enable-ssl" + EXTRA_ARGS=("--skip-tags" "system-upgrade") else echo -e "Invalid -s parameter." exit 1 @@ -149,15 +145,23 @@ sudo mkdir -p /etc/ansible echo -e "[local]\nlocalhost ansible_connection=local" | sudo tee /etc/ansible/hosts > /dev/null if [ ! -f /etc/locale.gen ]; then - # No locales found. Creating locales with default UK/US setup. - echo -e "en_GB.UTF-8 UTF-8\nen_US.UTF-8 UTF-8" | sudo tee /etc/locale.gen > /dev/null - sudo locale-gen + # No locales found. Creating locales with default UK/US setup. + echo -e "en_GB.UTF-8 UTF-8\nen_US.UTF-8 UTF-8" | sudo tee /etc/locale.gen > /dev/null + sudo locale-gen fi sudo sed -i 's/apt.screenlyapp.com/archive.raspbian.org/g' /etc/apt/sources.list sudo apt update -y -sudo apt-get purge -y python-setuptools python-pip python-pyasn1 -sudo apt-get install -y python-dev git-core libffi-dev libssl-dev whois +sudo apt-get purge -y \ + python-setuptools \ + python-pip \ + python-pyasn1 +sudo apt-get install -y \ + python-dev \ + git-core \ + libffi-dev \ + libssl-dev \ + whois curl -s https://bootstrap.pypa.io/get-pip.py | sudo python if [ "$NETWORK" == 'y' ]; then @@ -169,18 +173,60 @@ fi sudo pip install ansible==2.8.8 -sudo -u pi ansible localhost -m git -a "repo=$REPOSITORY dest=/home/pi/screenly version=$BRANCH force=no" +sudo -u pi ansible localhost \ + -m git \ + -a "repo=$REPOSITORY dest=/home/pi/screenly version=$BRANCH force=no" cd /home/pi/screenly/ansible -sudo -E ansible-playbook site.yml $EXTRA_ARGS +sudo -E ansible-playbook site.yml "${EXTRA_ARGS[@]}" + +sudo -E docker-compose \ + -f /home/pi/screenly/docker-compose.yml \ + -f /home/pi/screenly/docker-compose.override.yml \ + pull + +sudo -E docker-compose \ + -f /home/pi/screenly/docker-compose.yml \ + -f /home/pi/screenly/docker-compose.override.yml \ + up -d sudo apt-get autoclean sudo apt-get clean -sudo find /usr/share/doc -depth -type f ! -name copyright -delete -sudo find /usr/share/doc -empty -delete -sudo rm -rf /usr/share/man /usr/share/groff /usr/share/info/* /usr/share/lintian /usr/share/linda /var/cache/man -sudo find /usr/share/locale -type f ! -name 'en' ! -name 'de*' ! -name 'es*' ! -name 'ja*' ! -name 'fr*' ! -name 'zh*' -delete -sudo find /usr/share/locale -mindepth 1 -maxdepth 1 ! -name 'en*' ! -name 'de*' ! -name 'es*' ! -name 'ja*' ! -name 'fr*' ! -name 'zh*' ! -name 'locale.alias' -exec rm -r {} \; +sudo apt autoremove -y +sudo find /usr/share/doc \ + -depth \ + -type f \ + ! -name copyright \ + -delete +sudo find /usr/share/doc \ + -empty \ + -delete +sudo rm -rf \ + /usr/share/man \ + /usr/share/groff \ + /usr/share/info/* \ + /usr/share/lintian \ + /usr/share/linda /var/cache/man +sudo find /usr/share/locale \ + -type f \ + ! -name 'en' \ + ! -name 'de*' \ + ! -name 'es*' \ + ! -name 'ja*' \ + ! -name 'fr*' \ + ! -name 'zh*' \ + -delete +sudo find /usr/share/locale \ + -mindepth 1 \ + -maxdepth 1 \ + ! -name 'en*' \ + ! -name 'de*' \ + ! -name 'es*' \ + ! -name 'ja*' \ + ! -name 'fr*' \ + ! -name 'zh*' \ + ! -name 'locale.alias' \ + -exec rm -r {} \; cd /home/pi/screenly && git rev-parse HEAD > /home/pi/.screenly/latest_screenly_sha sudo chown -R pi:pi /home/pi @@ -206,7 +252,7 @@ local VAR_CURRENTPIUSERPW=$(sudo cat /etc/shadow | grep pi | awk -F ':' '{print local VAR_DEFAULTPIPW=$(mkpasswd -m sha-512 raspberry "$VAR_CURRENTPISALT") if [[ "$VAR_CURRENTPIUSERPW" == "$VAR_DEFAULTPIPW" ]]; then - echo "(Warning): The default raspberry pi password was detected! - please change it now..." + echo "(Warning): The default Raspberry Pi password was detected! - please change it now..." set +e passwd set -e diff --git a/bin/start_balena.sh b/bin/start_balena.sh deleted file mode 100755 index cf58c3834..000000000 --- a/bin/start_balena.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/bash - -run_setup () { - mkdir -p \ - /data/.config \ - /data/.config/uzbl \ - /data/.screenly \ - /data/screenly \ - /data/screenly_assets - - cp -n /tmp/screenly/ansible/roles/screenly/files/screenly.conf /data/.screenly/screenly.conf - cp -n /tmp/screenly/ansible/roles/screenly/files/default_assets.yml /data/.screenly/default_assets.yml - cp -n /tmp/screenly/ansible/roles/screenly/files/screenly.db /data/.screenly/screenly.db - cp -n /tmp/screenly/ansible/roles/screenly/files/uzbl-config /data/.config/uzbl/config-screenly - - cp -rf /tmp/screenly/* /data/screenly/ - - if [ -n "${OVERWRITE_CONFIG}" ]; then - echo "Requested to overwrite Screenly config file." - cp /data/screenly/ansible/roles/screenly/files/screenly.conf "/data/.screenly/screenly.conf" - fi - - # Set management page's user and password from environment variables, - # but only if both of them are provided. Can have empty values provided. - if [ -n "${MANAGEMENT_USER+x}" ] && [ -n "${MANAGEMENT_PASSWORD+x}" ]; then - sed -i -e "s/^user=.*/user=${MANAGEMENT_USER}/" -e "s/^password=.*/password=${MANAGEMENT_PASSWORD}/" /data/.screenly/screenly.conf - fi - - /usr/bin/python /data/screenly/bin/migrate.py -} - -run_viewer () { - # By default docker gives us 64MB of shared memory size but to display heavy - # pages we need more. - umount /dev/shm && mount -t tmpfs shm /dev/shm - - while true; do - - /usr/bin/X 0<&- &>/dev/null & - /usr/bin/matchbox-window-manager -use_titlebar no -use_cursor no 0<&- &>/dev/null & - - error=$(/usr/bin/xset s off 2>&1 | grep -c "unable to open display") - if [[ "$error" -eq 0 ]]; then - break - fi - - echo "Still continue..." - sleep 1 - done - - /usr/bin/xset -dpms - /usr/bin/xset s noblank - - while true; do - - error=$(curl screenly-server:8080 2>&1 | grep -c "Failed to connect") - if [[ "$error" -eq 0 ]]; then - break - fi - - echo "Still continue..." - sleep 1 - done - - cd /data/screenly - /usr/bin/python viewer.py -} - -run_server () { - service nginx start - - export RESIN_UUID=${RESIN_DEVICE_UUID} - - cd /data/screenly - /usr/bin/python server.py -} - -run_websocket () { - cd /data/screenly - /usr/bin/python websocket_server_layer.py -} - -run_celery () { - cd /data/screenly - celery worker -A server.celery -B -n worker@screenly --loglevel=info --schedule /tmp/celerybeat-schedule -} - -if [[ "$SCREENLYSERVICE" = "server" ]]; then - run_setup - run_server -fi - -if [[ "$SCREENLYSERVICE" = "viewer" ]]; then - run_viewer -fi - -if [[ "$SCREENLYSERVICE" = "websocket" ]]; then - run_websocket -fi - -if [[ "$SCREENLYSERVICE" = "celery" ]]; then - run_celery -fi diff --git a/bin/start_server.sh b/bin/start_server.sh new file mode 100755 index 000000000..3cb22ce5c --- /dev/null +++ b/bin/start_server.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +mkdir -p \ + /data/.config \ + /data/.screenly \ + /data/screenly_assets + +cp -n /usr/src/app/ansible/roles/screenly/files/screenly.conf /data/.screenly/screenly.conf +cp -n /usr/src/app/ansible/roles/screenly/files/default_assets.yml /data/.screenly/default_assets.yml +cp -n /usr/src/app/ansible/roles/screenly/files/screenly.db /data/.screenly/screenly.db + +if [ -n "${OVERWRITE_CONFIG}" ]; then + echo "Requested to overwrite Screenly config file." + cp /usr/src/app/ansible/roles/screenly/files/screenly.conf "/data/.screenly/screenly.conf" +fi + +# Set management page's user and password from environment variables, +# but only if both of them are provided. Can have empty values provided. +if [ -n "${MANAGEMENT_USER+x}" ] && [ -n "${MANAGEMENT_PASSWORD+x}" ]; then + sed -i -e "s/^user=.*/user=${MANAGEMENT_USER}/" -e "s/^password=.*/password=${MANAGEMENT_PASSWORD}/" /data/.screenly/screenly.conf +fi + +echo "Running migration..." +python ./bin/migrate.py + +python server.py diff --git a/bin/start_viewer.sh b/bin/start_viewer.sh new file mode 100755 index 000000000..e049cfb0c --- /dev/null +++ b/bin/start_viewer.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# Fixes permission on /dev/vchiq +chgrp video /dev/vchiq +chmod g+rwX /dev/vchiq + +# Set permission for sha file +chown viewer /dev/snd/* +chown viewer /data/.screenly/latest_screenly_sha + +# Fixes caching in QTWebEngine +mkdir -p /data/.local/share/ScreenlyWebview/QtWebEngine \ + /data/.cache/ScreenlyWebview \ + /data/.pki +chown -R viewer /data/.local/share/ScreenlyWebview +chown -R viewer /data/.cache/ScreenlyWebview/ +chown -R viewer /data/.pki + +# Temporary workaround for watchdog +touch /tmp/screenly.watchdog +chown viewer /tmp/screenly.watchdog + +# For whatever reason Raspbian messes up the sudo permissions +chown root:root /usr/bin/sudo +chown -R root:root /etc/sudoers.d +chown -R root:root /etc/sudo.conf +chown -R root:root /usr/lib/sudo +chown root:root /etc/sudoers +chmod 4755 /usr/bin/sudo + +# SUGUSR1 from the viewer is also sent to the container +# Prevent it so that the container does not fail +trap '' 16 + +sudo -E -u viewer dbus-run-session python viewer.py & + +# Waiting for the viewer +while true; do + PID=$(pidof python) + if [ "$?" == '0' ]; then + break + fi + sleep 0.5 +done + +# Exit when the viewer falls +while kill -0 "$PID"; do + sleep 1 +done diff --git a/docker-compose.demo.yml b/docker-compose.demo.yml index 7b843e2e8..b66da1968 100644 --- a/docker-compose.demo.yml +++ b/docker-compose.demo.yml @@ -14,6 +14,7 @@ services: - ./:/home/pi/screenly:ro - screenly-assets-volume:/home/pi/screenly_assets - screenly-volume:/home/pi/.screenly + screenly-celery: image: screenly/ose-dev-celery:latest restart: always @@ -27,6 +28,7 @@ services: - ./:/home/pi/screenly:ro - screenly-assets-volume:/home/pi/screenly_assets - screenly-volume:/home/pi/.screenly + redis: image: redis:alpine logging: diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 000000000..7d7e850ef --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,83 @@ +version: "2" +services: + srly-ose-server: + image: screenly/srly-ose-server:${DOCKER_TAG} + environment: + - HOME=/data + - LISTEN=0.0.0.0 + - CELERY_BROKER_URL=redis://redis:6379/0 + - CELERY_RESULT_BACKEND=redis://redis:6379/0 + restart: always + volumes: + - /home/pi/.screenly:/data/.screenly + - /home/pi/screenly_assets:/data/screenly_assets + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + + srly-ose-viewer: + image: screenly/srly-ose-viewer:${DOCKER_TAG}-${DEVICE_TYPE} + depends_on: + - srly-ose-server + environment: + - HOME=/data + - LISTEN=srly-ose-nginx + - PORT=80 + privileged: true + restart: always + volumes: + - /home/pi/.screenly:/data/.screenly + - /home/pi/screenly_assets:/data/screenly_assets + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + + srly-ose-websocket: + image: screenly/srly-ose-websocket:${DOCKER_TAG} + depends_on: + - srly-ose-server + environment: + - HOME=/data + - LISTEN=0.0.0.0 + privileged: true + restart: always + volumes: + - /home/pi/.screenly:/data/.screenly + - /home/pi/screenly_assets:/data/screenly_assets + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + + srly-ose-celery: + image: screenly/srly-ose-celery:${DOCKER_TAG} + depends_on: + - srly-ose-server + - redis + environment: + - HOME=/data + - CELERY_BROKER_URL=redis://redis:6379/0 + - CELERY_RESULT_BACKEND=redis://redis:6379/0 + privileged: true + restart: always + volumes: + - /home/pi/.screenly:/data/.screenly + - /home/pi/screenly_assets:/data/screenly_assets + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + + redis: + image: screenly/srly-ose-redis:${DOCKER_TAG} + + srly-ose-nginx: + image: screenly/srly-ose-nginx:${DOCKER_TAG} + environment: + - HOME=/data + depends_on: + - srly-ose-server + - srly-ose-websocket + restart: always + volumes: + - /home/pi/.screenly:/data/.screenly:ro + - /home/pi/screenly_assets:/data/screenly_assets:ro + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + +volumes: + screenly-data: diff --git a/docker-compose.yml b/docker-compose.yml index 62dc1103a..28d3fa3f7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,83 +1,89 @@ version: "2" services: - screenly-server: + srly-ose-server: + #image: screenly/srly-ose-server:latest build: context: . - dockerfile: docker/Dockerfile.server.template + dockerfile: docker/Dockerfile.server environment: - HOME=/data - LISTEN=0.0.0.0 - - PYTHONPATH=/data/screenly - - SCREENLYSERVICE=server - CELERY_BROKER_URL=redis://redis:6379/0 - CELERY_RESULT_BACKEND=redis://redis:6379/0 - ports: - - 80:8080 - privileged: true restart: always volumes: - resin-data:/data + labels: + io.balena.features.supervisor-api: '1' - screenly-viewer: + srly-ose-viewer: + #image: screenly/srly-ose-viewer:latest-pi3 build: context: . - dockerfile: docker/Dockerfile.viewer.template + dockerfile: docker/Dockerfile.viewer depends_on: - - screenly-server + - srly-ose-server environment: - - DISPLAY=:0.0 - HOME=/data - NOREFRESH=1 - - PYTHONPATH=/data/screenly - - SCREENLYSERVICE=viewer - - LISTEN=screenly-server - - PORT=8080 + - LISTEN=srly-ose-nginx privileged: true restart: always volumes: - resin-data:/data - screenly-websocket: + srly-ose-websocket: + #image: screenly/srly-ose-websocket:latest build: context: . - dockerfile: docker/Dockerfile.websocket.template + dockerfile: docker/Dockerfile.websocket depends_on: - - screenly-server + - srly-ose-server environment: - HOME=/data - - PYTHONPATH=/data/screenly - - SCREENLYSERVICE=websocket - - LISTEN=screenly-server - ports: - - 9999:9999 - privileged: true + - LISTEN=0.0.0.0 restart: always volumes: - resin-data:/data - screenly-celery: + srly-ose-celery: + #image: screenly/srly-ose-celery:latest build: context: . - dockerfile: docker/Dockerfile.celery.template + dockerfile: docker/Dockerfile.celery depends_on: - - screenly-server + - srly-ose-server - redis environment: - HOME=/data - - PYTHONPATH=/data/screenly - - SCREENLYSERVICE=celery - CELERY_BROKER_URL=redis://redis:6379/0 - CELERY_RESULT_BACKEND=redis://redis:6379/0 - privileged: true restart: always volumes: - resin-data:/data redis: + #image: screenly/srly-ose-redis:latest build: context: . - dockerfile: docker/Dockerfile.redis.template + dockerfile: docker/Dockerfile.redis restart: always + srly-ose-nginx: + #image: screenly/srly-ose-nginx:latest + build: + context: . + dockerfile: docker/Dockerfile.nginx + ports: + - 80:80 + environment: + - HOME=/data + depends_on: + - srly-ose-server + - srly-ose-websocket + restart: always + volumes: + - resin-data:/data:ro + volumes: resin-data: diff --git a/docker/Dockerfile.celery.template b/docker/Dockerfile.base similarity index 64% rename from docker/Dockerfile.celery.template rename to docker/Dockerfile.base index 73a32ac3b..adf9a2290 100644 --- a/docker/Dockerfile.celery.template +++ b/docker/Dockerfile.base @@ -1,31 +1,28 @@ -FROM balenalib/%%BALENA_MACHINE_NAME%%-debian:buster +FROM balenalib/rpi-raspbian:buster RUN apt-get update && \ apt-get -y install --no-install-recommends \ build-essential \ curl \ + ffmpeg \ + git \ git-core \ + ifupdown \ libffi-dev \ - libzmq3-dev \ + libraspberrypi0 \ libssl-dev \ + libzmq3-dev \ + lsb-release \ + mplayer \ net-tools \ omxplayer \ + procps \ psmisc \ python-dev \ python-gobject \ + python-pil \ python-pip \ python-setuptools \ - python-pil \ python-simplejson \ - libraspberrypi0 \ - ifupdown \ sqlite3 && \ apt-get clean - -# Install Python requirements -ADD requirements/requirements.txt /tmp/requirements.txt -RUN pip install --no-cache-dir -r /tmp/requirements.txt - -COPY . /tmp/screenly - -CMD ["bash", "/tmp/screenly/bin/start_balena.sh"] diff --git a/docker/Dockerfile.celery b/docker/Dockerfile.celery new file mode 100644 index 000000000..ff75179c2 --- /dev/null +++ b/docker/Dockerfile.celery @@ -0,0 +1,15 @@ +FROM screenly/srly-ose-base + +ADD requirements/requirements.txt /tmp/requirements.txt +RUN pip install --no-cache-dir -r /tmp/requirements.txt + +RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app +COPY . /usr/src/app/ + +CMD celery worker \ + -A server.celery \ + -B -n worker@screenly \ + --loglevel=info \ + --schedule \ + /tmp/celerybeat-schedule diff --git a/docker/Dockerfile.celery.dev b/docker/Dockerfile.celery.dev index a64733314..b195f332c 100644 --- a/docker/Dockerfile.celery.dev +++ b/docker/Dockerfile.celery.dev @@ -8,13 +8,14 @@ RUN apt-get update && \ git \ libffi-dev \ libssl-dev \ + lsb-release \ mplayer \ net-tools \ procps \ + python-pip \ + python-setuptools \ python-dev \ python-gobject \ - python-setuptools \ - python-pip \ python-pil \ python-simplejson \ sqlite3 \ @@ -23,7 +24,7 @@ RUN apt-get update && \ # Install Python requirements ADD requirements/requirements.txt /tmp/requirements.txt -RUN pip install -r /tmp/requirements.txt +RUN pip install --no-cache-dir -r /tmp/requirements.txt RUN useradd pi diff --git a/docker/Dockerfile.nginx b/docker/Dockerfile.nginx new file mode 100644 index 000000000..09c20a0d5 --- /dev/null +++ b/docker/Dockerfile.nginx @@ -0,0 +1,3 @@ +FROM nginx:1-alpine + +COPY docker/nginx/nginx.conf /etc/nginx/conf.d/srly-ose.conf diff --git a/docker/Dockerfile.redis.template b/docker/Dockerfile.redis similarity index 75% rename from docker/Dockerfile.redis.template rename to docker/Dockerfile.redis index 4fbadc39f..4ac3a4677 100644 --- a/docker/Dockerfile.redis.template +++ b/docker/Dockerfile.redis @@ -1,4 +1,4 @@ -FROM balenalib/%%BALENA_MACHINE_NAME%%-debian:buster +FROM balenalib/rpi-raspbian:buster RUN apt-get update && \ apt-get -y install --no-install-recommends \ diff --git a/docker/Dockerfile.server b/docker/Dockerfile.server new file mode 100644 index 000000000..292661919 --- /dev/null +++ b/docker/Dockerfile.server @@ -0,0 +1,10 @@ +FROM screenly/srly-ose-base + +ADD requirements/requirements.txt /tmp/requirements.txt +RUN pip install --no-cache-dir -r /tmp/requirements.txt + +RUN mkdir -p /usr/src/app +COPY . /usr/src/app/ +WORKDIR /usr/src/app + +CMD ["bash", "bin/start_server.sh"] diff --git a/docker/Dockerfile.server.dev b/docker/Dockerfile.server.dev index e899e3530..8982e4b36 100644 --- a/docker/Dockerfile.server.dev +++ b/docker/Dockerfile.server.dev @@ -40,10 +40,6 @@ RUN chown -R pi:pi /home/pi/.screenly /home/pi/screenly_assets USER pi WORKDIR /home/pi/screenly -ENV LANG en_US.UTF-8 -ENV LANGUAGE en_US:en -ENV LC_ALL en_US.UTF-8 - EXPOSE 8080 CMD python server.py diff --git a/docker/Dockerfile.server.template b/docker/Dockerfile.server.template deleted file mode 100644 index d77e67289..000000000 --- a/docker/Dockerfile.server.template +++ /dev/null @@ -1,35 +0,0 @@ -FROM balenalib/%%BALENA_MACHINE_NAME%%-debian:buster - -RUN apt-get update && \ - apt-get -y install --no-install-recommends \ - build-essential \ - curl \ - ffmpeg \ - git \ - libffi-dev \ - libssl-dev \ - lsb-release \ - mplayer \ - net-tools \ - procps \ - python-pip \ - python-setuptools \ - python-dev \ - python-gobject \ - python-pil \ - python-simplejson \ - sqlite3 \ - && \ - apt-get clean - -# Install Python requirements -ADD requirements/requirements.txt /tmp/requirements.txt -RUN pip install --no-cache-dir -r /tmp/requirements.txt - -# Setup nginx -RUN rm -f /etc/nginx/sites-enabled/default -COPY ansible/roles/ssl/files/nginx_resin.conf /etc/nginx/sites-enabled/screenly.conf - -COPY . /tmp/screenly - -CMD ["bash", "/tmp/screenly/bin/start_balena.sh"] diff --git a/docker/Dockerfile.viewer b/docker/Dockerfile.viewer new file mode 100644 index 000000000..1ad0acfbe --- /dev/null +++ b/docker/Dockerfile.viewer @@ -0,0 +1,151 @@ +FROM balenalib/rpi-raspbian:buster + +# This list needs to be trimmed back later +RUN apt-get update && \ + apt-get -y install \ + build-essential \ + ca-certificates \ + git-core \ + gstreamer1.0-plugins-base \ + gstreamer1.0-plugins-good \ + gstreamer1.0-plugins-ugly \ + gstreamer1.0-x \ + libasound2-dev \ + libavcodec-dev \ + libavformat-dev \ + libavutil-dev \ + libbz2-dev \ + libdbus-1-dev \ + libdbus-glib-1-dev \ + libdrm-dev \ + libegl1-mesa-dev \ + libevent-dev \ + libffi-dev \ + libfontconfig1-dev \ + libfreetype6-dev \ + libgbm-dev \ + libgcrypt20-dev \ + libgles2-mesa \ + libgles2-mesa-dev \ + libglib2.0-dev \ + libgst-dev \ + libgstreamer-plugins-base0.10-dev \ + libgstreamer0.10-dev \ + libicu-dev \ + libinput-dev \ + libiodbc2-dev \ + libjpeg62-turbo-dev \ + libjsoncpp-dev \ + libminizip-dev \ + libnss3 \ + libnss3-dev \ + libopus-dev \ + libpci-dev \ + libpng-dev \ + libpng16-16 \ + libpq-dev \ + libpulse-dev \ + libraspberrypi0 \ + librsvg2-common \ + libsdl2-dev \ + libsnappy-dev \ + libsqlite0-dev \ + libsqlite3-dev \ + libsrtp0-dev \ + libsrtp2-dev \ + libssl-dev \ + libssl1.1 \ + libswscale-dev \ + libsystemd-dev \ + libts-dev \ + libudev-dev \ + libvpx-dev \ + libwebp-dev \ + libx11-dev \ + libx11-xcb-dev \ + libx11-xcb1 \ + libxcb-glx0-dev \ + libxcb-icccm4 \ + libxcb-icccm4-dev \ + libxcb-image0 \ + libxcb-image0-dev \ + libxcb-keysyms1 \ + libxcb-keysyms1-dev \ + libxcb-randr0-dev \ + libxcb-render-util0 \ + libxcb-render-util0-dev \ + libxcb-shape0-dev \ + libxcb-shm0 \ + libxcb-shm0-dev \ + libxcb-sync-dev \ + libxcb-sync1 \ + libxcb-xfixes0-dev \ + libxcb-xinerama0 \ + libxcb-xinerama0-dev \ + libxcb1 \ + libxcb1-dev \ + libxext-dev \ + libxi-dev \ + libxkbcommon-dev \ + libxrender-dev \ + libxslt1-dev \ + libxss-dev \ + libxtst-dev \ + net-tools \ + omxplayer \ + vlc \ + psmisc \ + python-dev \ + python-gobject \ + python-netifaces \ + python-pip \ + python-setuptools \ + sqlite3 && \ + apt-get clean + +# Install Python requirements +ADD requirements/requirements.viewer.txt /tmp/requirements.txt +RUN pip install --no-cache-dir -r /tmp/requirements.txt + +# Works around issue with `curl` +# https://github.com/balena-io-library/base-images/issues/562 +RUN c_rehash + +# QT Base from packages does not support eglfs +ARG PI_VERSION=pi3 +ARG DEBIAN_VERSION=buster +ARG QT_VERSION=5.15.2 +ARG WEBVIEW_GIT_HASH=349cbe4 +RUN curl "https://storage.googleapis.com/ose-lab/qt5-$QT_VERSION-$DEBIAN_VERSION-$PI_VERSION.tar.gz" \ + -s -o /tmp/qt5-$QT_VERSION-$DEBIAN_VERSION-$PI_VERSION.tar.gz && \ + curl "https://storage.googleapis.com/ose-lab/qt5-$QT_VERSION-$DEBIAN_VERSION-$PI_VERSION.tar.gz.sha256" \ + -s -o /tmp/qt5-$QT_VERSION-$DEBIAN_VERSION-$PI_VERSION.tar.gz.sha256 && \ + cd /tmp && \ + sha256sum -c qt5-$QT_VERSION-$DEBIAN_VERSION-$PI_VERSION.tar.gz.sha256 && \ + tar -xzf /tmp/qt5-$QT_VERSION-$DEBIAN_VERSION-$PI_VERSION.tar.gz -C /usr/local && \ + rm qt5-$QT_VERSION-$DEBIAN_VERSION-$PI_VERSION.tar.gz* + +RUN curl "https://storage.googleapis.com/ose-lab/webview-$QT_VERSION-$DEBIAN_VERSION-$PI_VERSION-$WEBVIEW_GIT_HASH.tar.gz" \ + -s -o /tmp/webview-$QT_VERSION-$DEBIAN_VERSION-$PI_VERSION-$WEBVIEW_GIT_HASH.tar.gz && \ + curl "https://storage.googleapis.com/ose-lab/webview-$QT_VERSION-$DEBIAN_VERSION-$PI_VERSION-$WEBVIEW_GIT_HASH.tar.gz.sha256" \ + -s -o /tmp/webview-$QT_VERSION-$DEBIAN_VERSION-$PI_VERSION-$WEBVIEW_GIT_HASH.tar.gz.sha256 && \ + cd /tmp && \ + sha256sum -c webview-$QT_VERSION-$DEBIAN_VERSION-$PI_VERSION-$WEBVIEW_GIT_HASH.tar.gz.sha256 && \ + tar -xzf /tmp/webview-$QT_VERSION-$DEBIAN_VERSION-$PI_VERSION-$WEBVIEW_GIT_HASH.tar.gz -C /usr/local && \ + rm webview-$QT_VERSION-$DEBIAN_VERSION-$PI_VERSION-$WEBVIEW_GIT_HASH.tar.gz* + +ENV QT_QPA_EGLFS_FORCE888=1 +ENV QT_QPA_PLATFORM=linuxfb + +# Turn on debug logging for now +#ENV QT_LOGGING_RULES=qt.qpa.*=true +ENV QT_LOGGING_RULES=*.debug=true +ENV QT_QPA_DEBUG=1 + +RUN useradd -g video viewer + +WORKDIR /usr/src/app +RUN mkdir -p /usr/src/app +COPY . /usr/src/app/ + +CMD ["bash", "./bin/start_viewer.sh"] diff --git a/docker/Dockerfile.viewer.template b/docker/Dockerfile.viewer.template deleted file mode 100644 index c52d70dd9..000000000 --- a/docker/Dockerfile.viewer.template +++ /dev/null @@ -1,36 +0,0 @@ -FROM balenalib/%%BALENA_MACHINE_NAME%%-debian:buster - -RUN apt-get update && \ - apt-get -y install --no-install-recommends \ - build-essential \ - curl \ - git-core \ - ifupdown \ - libffi-dev \ - libraspberrypi0 \ - libssl-dev \ - matchbox \ - net-tools \ - omxplayer \ - psmisc \ - python-dev \ - python-pil \ - python-pip \ - python-setuptools \ - python-simplejson \ - sqlite3 \ - uzbl \ - x11-xserver-utils \ - xserver-xorg && \ - apt-get clean - -# Install Python requirements -ADD requirements/requirements.txt /tmp/requirements.txt -RUN pip install --no-cache-dir -r /tmp/requirements.txt - -COPY ansible/roles/screenly/files/gtkrc-2.0 /data/.gtkrc-2.0 - -COPY . /tmp/screenly - -CMD ["bash", "chmod 777 /dev/vchiq"] -CMD ["bash", "/tmp/screenly/bin/start_balena.sh"] diff --git a/docker/Dockerfile.websocket b/docker/Dockerfile.websocket new file mode 100644 index 000000000..b4241d959 --- /dev/null +++ b/docker/Dockerfile.websocket @@ -0,0 +1,10 @@ +FROM screenly/srly-ose-base + +ADD requirements/requirements-websocket.txt /tmp/requirements.txt +RUN pip install --no-cache-dir -r /tmp/requirements.txt + +RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app +COPY . /usr/src/app/ + +CMD ["python", "websocket_server_layer.py"] diff --git a/docker/Dockerfile.websocket.template b/docker/Dockerfile.websocket.template deleted file mode 100644 index 8862d5659..000000000 --- a/docker/Dockerfile.websocket.template +++ /dev/null @@ -1,19 +0,0 @@ -FROM balenalib/%%BALENA_MACHINE_NAME%%-debian:buster - -RUN apt-get update && \ - apt-get -y install --no-install-recommends \ - build-essential \ - curl \ - libffi-dev \ - python-pip \ - python-setuptools \ - python-dev && \ - apt-get clean - -# Install Python requirements -ADD requirements/requirements-websocket.txt /tmp/requirements.txt -RUN pip install --no-cache-dir -r /tmp/requirements.txt - -COPY . /tmp/screenly - -CMD ["bash", "/tmp/screenly/bin/start_balena.sh"] diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf new file mode 100644 index 000000000..aa979178e --- /dev/null +++ b/docker/nginx/nginx.conf @@ -0,0 +1,90 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +upstream ose { + server srly-ose-server:8080; +} + +upstream wifi-connect { + server 192.168.42.1:9090; +} + +upstream websocket { + server srly-ose-websocket:9999; +} + +server { + server_tokens off; + listen 80 default_server; + + location / { + + # Temporarily disables wifi-connect + proxy_pass http://ose; + + #if (-f /data/.screenly/initialized) { + # proxy_pass http://ose; + #} + #if (!-f /data/.screenly/initialized) { + # proxy_pass http://wifi-connect; + #} + + client_max_body_size 4G; + 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; + } + + location ~ ^/api/[0-9a-z]+/backup$ { + proxy_pass http://ose; + proxy_connect_timeout 1800; + proxy_send_timeout 1800; + proxy_read_timeout 1800; + send_timeout 1800; + + client_max_body_size 4G; + 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; + } + + location /static { + proxy_pass http://ose/static; + } + + location /ws { + proxy_pass http://websocket; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } + + location /hotspot { + # Only allow from Docker's CIDR + allow 172.16.0.0/12; + deny all; + + if (!-f /data/.screenly/initialized) { + root /tmp; + rewrite ^ /hotspot.html break; + } + } + + location /screenly_assets { + allow 172.16.0.0/12; + deny all; + + alias /data/screenly_assets; + } +} + +server { + # Only allow from localhost and Docker's CIDR + allow 172.16.0.0/12; + allow 172.0.0.1; + deny all; + + server_name *.ngrok.io; + listen 80; + root /data/screenly_assets; + try_files $uri /data/screenly_assets$uri; +} diff --git a/docker/start.sh b/docker/start.sh deleted file mode 100755 index b0008501e..000000000 --- a/docker/start.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -FILE="$DIR/../docker-compose.dev.yml" -docker-compose -f "$FILE" "$@" diff --git a/docs/developer-documentation.md b/docs/developer-documentation.md index 3936cab11..e22df7ae0 100644 --- a/docs/developer-documentation.md +++ b/docs/developer-documentation.md @@ -22,6 +22,10 @@ There are currently three versions of Screenly-OSE.. | Experimental | [experimental](https://github.com/Screenly/screenly-ose/tree/experimental) | This is the branch for experimenting, such as using a new web browser | +### Docker and Directories + +/ + ### Directories, files and their purpose with regards to Screenly ``` @@ -84,8 +88,15 @@ screenly.script -> plymouth script file that loads and scales splashscreen image `/other/directories/here/.. from ansible roles` -### Screenly-OSE-WebView +### Debugging Screenly OSE webview + +``` +export QT_LOGGING_DEBUG=1 +export QT_LOGGING_RULES="*.debug=true" +export QT_QPA_EGLFS_DEBUG=1 +``` Screenly OSE WebView is a custom-built web browser based on the [QT](https://www.qt.io/) toolkit framework. The browser is assembled with a Dockerfile and built by the `built_qtbase.sh` script. + For further info on these files and more, visit the following link: `https://github.com/Screenly/screenly-ose/master/webview` diff --git a/lib/html_templates.py b/lib/html_templates.py deleted file mode 100644 index f53bae478..000000000 --- a/lib/html_templates.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- - - -def black_page(filepath): - html = """ -
- - - -""" - - with open(filepath, 'w') as f: - f.write(html) - return filepath diff --git a/lib/media_player.py b/lib/media_player.py new file mode 100644 index 000000000..91754bb0f --- /dev/null +++ b/lib/media_player.py @@ -0,0 +1,82 @@ +from platform import machine + +import sh +import vlc + +from settings import settings + +VIDEO_TIMEOUT = 20 # secs + + +class MediaPlayer: + def __init__(self): + pass + + def set_asset(self, uri, duration): + raise NotImplementedError + + def play(self): + raise NotImplementedError + + def stop(self): + raise NotImplementedError + + def is_playing(self): + raise NotImplementedError + + +class VLCMediaPlayer(MediaPlayer): + def __init__(self): + MediaPlayer.__init__(self) + self.instance = vlc.Instance() + self.player = self.instance.media_player_new() + + self.player.audio_output_set('alsa') + + def set_asset(self, uri, duration): + # @TODO: HDMI or 3.5mm jack audio output + self.player.set_mrl(uri) + + def play(self): + self.player.play() + + def stop(self): + self.player.stop() + + def is_playing(self): + return self.player.get_state() in [vlc.State.Playing, vlc.State.Buffering, vlc.State.Opening] + + +class OMXMediaPlayer(MediaPlayer): + def __init__(self): + MediaPlayer.__init__(self) + self._arch = machine() + + self._run = None + self._player_args = list() + self._player_kwargs = dict() + + def set_asset(self, uri, duration): + settings.load() + + if self._arch in ('armv6l', 'armv7l'): + self._player_args = ['omxplayer', uri] + self._player_kwargs = {'o': settings['audio_output'], 'layer': 1, '_bg': True, '_ok_code': [0, 124, 143]} + else: + self._player_args = ['mplayer', uri, '-nosound'] + self._player_kwargs = {'_bg': True, '_ok_code': [0, 124]} + + if duration and duration != 'N/A': + self._player_args = ['timeout', VIDEO_TIMEOUT + int(duration.split('.')[0])] + self._player_args + + def play(self): + self._run = sh.Command(self._player_args[0])(*self._player_args[1:], **self._player_kwargs) + + def stop(self): + try: + sh.killall('omxplayer.bin', _ok_code=[1]) + except OSError: + pass + + def is_playing(self): + return bool(self._run.process.alive) diff --git a/lib/utils.py b/lib/utils.py index d6adb7a03..bbdefb5a2 100644 --- a/lib/utils.py +++ b/lib/utils.py @@ -28,24 +28,17 @@ arch = machine() # 300 level HTTP responses are also ok, such as redirects, which many sites have and load +# @TODO: This should be replaced with `r.ok` instead. HTTP_OK = xrange(200, 399) # This will only work on the Raspberry Pi, # so let's wrap it in a try/except so that # Travis can run. try: - from sh import omxplayer + from sh import ffprobe except ImportError: pass -# This will work on x86-based machines -if machine() in ['x86', 'x86_64']: - try: - from sh import ffprobe, mplayer - except ImportError: - pass - - def string_to_bool(string): return bool(strtobool(str(string))) @@ -87,8 +80,7 @@ def get_node_ip(retry=3, timeout=1): for attempt in range(1, retry + 1): try: default_interface = gateways()['default'][AF_INET][1] - my_ip = ifaddresses(default_interface)[AF_INET][0]['addr'] - return my_ip + return ifaddresses(default_interface)[AF_INET][0]['addr'] except (KeyError, ValueError): if attempt == retry: break @@ -178,10 +170,7 @@ def get_video_duration(file): time = None try: - if arch in ('armv6l', 'armv7l'): - run_player = omxplayer(file, info=True, _err_to_out=True, _ok_code=[0, 1], _decode_errors='ignore') - else: - run_player = ffprobe('-i', file, _err_to_out=True) + run_player = ffprobe('-i', file, _err_to_out=True) except sh.ErrorReturnCode_1: raise Exception('Bad video format') @@ -218,18 +207,11 @@ def url_fails(url): If it is streaming """ if urlparse(url).scheme in ('rtsp', 'rtmp'): - if arch in ('armv6l', 'armv7l'): - run_omxplayer = omxplayer(url, info=True, _err_to_out=True, _ok_code=[0, 1]) - for line in run_omxplayer.split('\n'): - if 'Input #0' in line: - return False - return True - else: - run_mplayer = mplayer('-identify', '-frames', '0', '-nosound', url) - for line in run_mplayer.split('\n'): - if 'Clip info:' in line: - return False - return True + run_mplayer = mplayer('-identify', '-frames', '0', '-nosound', url) + for line in run_mplayer.split('\n'): + if 'Clip info:' in line: + return False + return True """ Try HEAD and GET for URL availability check. @@ -331,6 +313,10 @@ def generate_perfect_paper_password(pw_length=10, has_symbols=True): return "".join(random.SystemRandom().choice(ppp_letters) for _ in range(pw_length)) +def is_docker(): + return os.path.isfile('/.dockerenv') + + def is_balena_app(): """ Checks the application is running on Balena Cloud diff --git a/package-lock.json b/package-lock.json index 705a75280..ffe186c6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,12 @@ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.3.1.tgz", "integrity": "sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag==" }, + "coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", + "dev": true + }, "css-toggle-switch": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/css-toggle-switch/-/css-toggle-switch-4.1.0.tgz", diff --git a/package.json b/package.json index 48535251a..7599217fc 100644 --- a/package.json +++ b/package.json @@ -4,5 +4,8 @@ "dependencies": { "bootstrap": "^4.3.1", "css-toggle-switch": "^4.1.0" + }, + "devDependencies": { + "coffee-script": "^1.12.7" } } diff --git a/requirements/requirements.host.txt b/requirements/requirements.host.txt new file mode 100644 index 000000000..a3d2b8919 --- /dev/null +++ b/requirements/requirements.host.txt @@ -0,0 +1,2 @@ +docker==4.3.1 +docker-compose==1.26.2 diff --git a/requirements/requirements.txt b/requirements/requirements.txt index b76c2a8bc..6e7b7b718 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -5,7 +5,7 @@ cffi==1.14.3 click==7.1.2 configparser==4.0.2 cryptography==3.2.1 -Flask-RESTful==0.3.8 +docker-py==1.10.6 Flask-Cors==3.0.9 flask-restful-swagger-2==0.35 flask-swagger-ui==3.36.0 diff --git a/requirements/requirements.viewer.txt b/requirements/requirements.viewer.txt new file mode 100644 index 000000000..2f42ddfcb --- /dev/null +++ b/requirements/requirements.viewer.txt @@ -0,0 +1,16 @@ +certifi==2020.6.20 +configparser==4.0.2 +cryptography==3.2.1 +Flask==1.1.2 +idna==2.6 +mixpanel==4.7.0 +netifaces==0.10.9 +pydbus==0.6.0 +python-dateutil==2.8.1 +python-vlc==3.0.11115 +pytz==2020.1 +pyzmq==19.0.2 +requests[security]==2.24.0 +sh==1.8 +uptime==3.0.1 +urllib3==1.25.11 diff --git a/server.py b/server.py index d1bbc25e8..0c53867f7 100755 --- a/server.py +++ b/server.py @@ -12,6 +12,7 @@ import sh import shutil import time + import traceback import yaml import uuid @@ -21,7 +22,7 @@ from dateutil import parser as date_parser from functools import wraps from hurry.filesize import size -from mimetypes import guess_type +from mimetypes import guess_type, guess_extension from os import getenv, listdir, makedirs, mkdir, path, remove, rename, statvfs, stat, walk from subprocess import check_output from urlparse import urlparse @@ -41,14 +42,14 @@ from lib import queries from lib.auth import authorized -from lib.utils import generate_perfect_paper_password +from lib.utils import generate_perfect_paper_password, is_docker from lib.utils import get_active_connections, remove_connection from lib.utils import get_node_ip, get_node_mac_address from lib.utils import get_video_duration from lib.utils import download_video_from_youtube, json_dump from lib.utils import url_fails from lib.utils import validate_url -from lib.utils import is_balena_app, is_demo_node, is_wott_integrated, get_wott_device_id +from lib.utils import is_balena_app, is_demo_node from settings import CONFIGURABLE_SETTINGS, DEFAULTS, LISTEN, PORT, settings, ZmqPublisher, ZmqCollector @@ -538,9 +539,11 @@ def get(key): if not asset_id: asset['asset_id'] = uuid.uuid4().hex - if uri.startswith('/'): - rename(uri, path.join(settings['assetdir'], asset['asset_id'])) - uri = path.join(settings['assetdir'], asset['asset_id']) + + if not asset_id and uri.startswith('/'): + new_uri = "{}{}".format(path.join(settings['assetdir'], asset['asset_id']), get('ext')) + rename(uri, new_uri) + uri = new_uri if 'youtube_asset' in asset['mimetype']: uri, asset['name'], asset['duration'] = download_video_from_youtube(uri, asset['asset_id']) @@ -1218,7 +1221,7 @@ def post(self): else: file_upload.save(file_path) - return file_path + return {'uri': file_path, 'ext': guess_extension(file_type)} class PlaylistOrder(Resource): @@ -1455,8 +1458,8 @@ def get(self): viewlog = None try: viewlog = [line.decode('utf-8') for line in - check_output(['sudo', 'systemctl', 'status', 'screenly-viewer.service', '-n', '20']).split('\n')] - except: + check_output(['journalctl', '-b', 'CONTAINER_NAME=screenly-ose-viewer', '-n', '20']).split('\n')] + except Exception: pass # Calculate disk space @@ -1464,7 +1467,7 @@ def get(self): free_space = size(slash.f_bavail * slash.f_frsize) return { - 'viewlog': viewlog, + # 'viewlog': viewlog, 'loadavg': diagnostics.get_load_avg()['15 min'], 'free_space': free_space, 'display_info': diagnostics.get_monitor_status(), @@ -1611,7 +1614,7 @@ def get(self): try: my_ip = get_node_ip() -except: +except Exception: pass else: SWAGGER_URL = '/api/docs' @@ -1652,7 +1655,7 @@ def viewIndex(): if settings['use_ssl']: ws_addresses.append('wss://' + my_ip + '/ws/') else: - ws_addresses.append('ws://' + my_ip + ':' + settings['websocket_port']) + ws_addresses.append('ws://' + my_ip + '/ws/') if resin_uuid: ws_addresses.append('wss://{}.resindevice.io/ws/'.format(resin_uuid)) @@ -1739,6 +1742,7 @@ def settings_page(): 'user': settings['user'], 'need_current_password': bool(settings['auth_backend']), 'is_balena': is_balena_app(), + 'is_docker': is_docker(), 'auth_backend': settings['auth_backend'], 'auth_backends': auth_backends }) @@ -1751,7 +1755,7 @@ def settings_page(): def system_info(): try: viewlog = [line.decode('utf-8') for line in - check_output(['sudo', 'systemctl', 'status', 'screenly-viewer.service', '-n', '20']).split('\n')] + check_output(['journalctl', '-b', 'CONTAINER_NAME=screenly-ose-viewer', '-n', '20']).split('\n')] except Exception: viewlog = None @@ -1801,7 +1805,7 @@ def system_info(): return template( 'system-info.html', player_name=player_name, - viewlog=viewlog, + # viewlog=viewlog, loadavg=loadavg, free_space=free_space, uptime=system_uptime, @@ -1821,7 +1825,6 @@ def integrations(): context = { 'player_name': settings['player_name'], 'is_balena': is_balena_app(), - 'is_wott_installed': is_wott_integrated(), } if context['is_balena']: @@ -1832,32 +1835,13 @@ def integrations(): context['balena_host_os_version'] = getenv('BALENA_HOST_OS_VERSION') context['balena_device_name_at_init'] = getenv('BALENA_DEVICE_NAME_AT_INIT') - if context['is_wott_installed']: - context['wott_device_id'] = get_wott_device_id() - return template('integrations.html', **context) @app.route('/splash-page') def splash_page(): - url = None - try: - my_ip = get_node_ip() - except Exception as e: - ip_lookup = False - error_msg = e - else: - ip_lookup = True - - if settings['use_ssl']: - url = 'https://{}'.format(my_ip) - elif LISTEN == '127.0.0.1': - url = "http://{}".format(my_ip) - else: - url = "http://{}:{}".format(my_ip, PORT) - - msg = url if url else error_msg - return template('splash-page.html', ip_lookup=ip_lookup, msg=msg) + my_ip = get_node_ip() + return template('splash-page.html', my_ip=get_node_ip()) @app.errorhandler(403) diff --git a/settings.py b/settings.py index 394a20311..4eff112fe 100644 --- a/settings.py +++ b/settings.py @@ -151,12 +151,12 @@ class ZmqPublisher: def __init__(self): if self.INSTANCE is not None: - raise ValueError("An instantiation already exists!") + raise ValueError("An instance already exists!") self.context = zmq.Context() self.socket = self.context.socket(zmq.PUB) - self.socket.bind('tcp://127.0.0.1:10001') + self.socket.bind('tcp://0.0.0.0:10001') sleep(1) @classmethod @@ -178,7 +178,7 @@ def __init__(self): self.socket = self.context.socket(zmq.PUSH) self.socket.setsockopt(zmq.LINGER, 0) - self.socket.connect('tcp://{}:5558'.format(LISTEN)) + self.socket.connect('tcp://srly-ose-server:5558') sleep(1) @@ -191,12 +191,12 @@ class ZmqCollector: def __init__(self): if self.INSTANCE is not None: - raise ValueError("An instantiation already exists!") + raise ValueError("An instance already exists!") self.context = zmq.Context() self.socket = self.context.socket(zmq.PULL) - self.socket.bind('tcp://127.0.0.1:5558') + self.socket.bind('tcp://0.0.0.0:5558') self.poller = zmq.Poller() self.poller.register(self.socket, zmq.POLLIN) diff --git a/static/js/screenly-ose.coffee b/static/js/screenly-ose.coffee index 061a87853..637da4164 100644 --- a/static/js/screenly-ose.coffee +++ b/static/js/screenly-ose.coffee @@ -35,7 +35,7 @@ now = -> new Date() get_template = (name) -> _.template ($ "##{name}-template").html() delay = (wait, fn) -> _.delay fn, wait -mimetypes = [ [('jpg jpeg png pnm gif bmp'.split ' '), 'image'] +mimetypes = [ [('jpe jpg jpeg png pnm gif bmp'.split ' '), 'image'] [('avi mkv mov mpg mpeg mp4 ts flv'.split ' '), 'video']] viduris = ('rtsp rtmp'.split ' ') domains = [ [('www.youtube.com youtu.be'.split ' '), 'youtube_asset']] @@ -218,8 +218,8 @@ API.View.AddAssetView = class AddAssetView extends Backbone.View that.viewmodel model data.submit() - .success (uri) -> - model.set {uri: uri}, silent:yes + .success (data) -> + model.set {uri: data.uri, ext: data.ext}, silent:yes save = model.save() save.done (data) -> diff --git a/static/js/screenly-ose.js b/static/js/screenly-ose.js index bfd31c532..92d5136cc 100644 --- a/static/js/screenly-ose.js +++ b/static/js/screenly-ose.js @@ -1,4 +1,4 @@ -// Generated by CoffeeScript 1.9.3 +// Generated by CoffeeScript 1.12.7 /* screenly-ose ui */ @@ -64,7 +64,7 @@ return _.delay(fn, wait); }; - mimetypes = [['jpg jpeg png pnm gif bmp'.split(' '), 'image'], ['avi mkv mov mpg mpeg mp4 ts flv'.split(' '), 'video']]; + mimetypes = [['jpe jpg jpeg png pnm gif bmp'.split(' '), 'image'], ['avi mkv mov mpg mpeg mp4 ts flv'.split(' '), 'video']]; viduris = 'rtsp rtmp'.split(' '); @@ -378,10 +378,11 @@ that.$fv('name', filename); that.updateFileUploadMimetype(filename); that.viewmodel(model); - return data.submit().success(function(uri) { + return data.submit().success(function(data) { var save; model.set({ - uri: uri + uri: data.uri, + ext: data.ext }, { silent: true }); @@ -1115,8 +1116,8 @@ return save = model.fetch(); } }); - } catch (_error) { - error = _error; + } catch (error1) { + error = error1; results.push(false); } } diff --git a/static/js/screenly-ose.js.map b/static/js/screenly-ose.js.map new file mode 100644 index 000000000..3bdfbca95 --- /dev/null +++ b/static/js/screenly-ose.js.map @@ -0,0 +1,10 @@ +{ + "version": 3, + "file": "screenly-ose.js", + "sourceRoot": "", + "sources": [ + "screenly-ose.coffee" + ], + "names": [], + "mappings": "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" +} \ No newline at end of file diff --git a/static/js/settings.js b/static/js/settings.js index b577b5d6d..a96446c27 100644 --- a/static/js/settings.js +++ b/static/js/settings.js @@ -1,4 +1,4 @@ -// Generated by CoffeeScript 1.9.3 +// Generated by CoffeeScript 1.12.7 (function() { $().ready(function() { var end_date, end_date_usb_file, start_date, start_date_usb_file, toggle_chunk; diff --git a/static/js/settings.js.map b/static/js/settings.js.map new file mode 100644 index 000000000..dbe556573 --- /dev/null +++ b/static/js/settings.js.map @@ -0,0 +1,10 @@ +{ + "version": 3, + "file": "settings.js", + "sourceRoot": "", + "sources": [ + "settings.coffee" + ], + "names": [], + "mappings": "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" +} \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index 33cb65dcc..9c850cf85 100644 --- a/templates/base.html +++ b/templates/base.html @@ -17,11 +17,11 @@To manage the content on this screen, just point your browser to:
{% else %} -{{ context.msg }}
+Unable to retrieve IP
{% endif %}The page you're trying to open is protected.
To display it, specify the asset URL
in the following format: