From 62c86faf7f85653dfd3f4d2f4d1d76f9b75b6445 Mon Sep 17 00:00:00 2001 From: accetto <34798830+accetto@users.noreply.github.com> Date: Sat, 12 Dec 2020 18:02:54 +0100 Subject: [PATCH] Initial release 2020-12-12 --- .github/workflows/deploy-readme.sh | 88 ++++ .github/workflows/dockerhub-autobuild.yml | 44 ++ .github/workflows/dockerhub-post-push.yml | 59 +++ CHANGELOG.md | 25 + LICENSE | 21 + README.md | 158 ++++++ docker/Dockerfile | 4 + docker/Dockerfile.xfce | 275 ++++++++++ docker/Dockerfile.xfce.chromium | 326 ++++++++++++ docker/Dockerfile.xfce.firefox | 322 ++++++++++++ docker/README.md | 3 + docker/hooks/build | 46 ++ docker/hooks/env.rc | 194 +++++++ docker/hooks/example-secrets.rc | 78 +++ docker/hooks/post_push | 93 ++++ docker/hooks/pre_build | 83 +++ docker/hooks/push | 65 +++ docker/hooks/util.rc | 256 +++++++++ docker/xfce-chromium/README-dockerhub.md | 124 +++++ docker/xfce-chromium/README.md | 414 +++++++++++++++ docker/xfce-chromium/readme-append.template | 26 + .../src/home/Desktop/chromium-browser.desktop | 295 +++++++++++ .../src/startup/version_sticker.sh | 62 +++ .../ubuntu-vnc-xfce-chromium.jpg | Bin 0 -> 64308 bytes docker/xfce-firefox/README-dockerhub.md | 142 +++++ docker/xfce-firefox/README.md | 487 ++++++++++++++++++ docker/xfce-firefox/readme-append.template | 42 ++ .../home/Desktop/Copy FF Preferences.desktop | 11 + .../home/Desktop/FF Profile Manager.desktop | 10 + .../src/firefox.plus/resources/accetto.svg | 116 +++++ .../copy_firefox_user_preferences.sh | 196 +++++++ .../src/firefox.plus/resources/user.js | 6 + .../src/home/Desktop/firefox.desktop | 222 ++++++++ .../src/startup/version_sticker.sh | 62 +++ .../ubuntu-vnc-xfce-firefox-plus.jpg | Bin 0 -> 67981 bytes .../xfce-firefox/ubuntu-vnc-xfce-firefox.jpg | Bin 0 -> 64304 bytes docker/xfce/README-dockerhub.md | 128 +++++ docker/xfce/README.md | 409 +++++++++++++++ docker/xfce/readme-append.template | 42 ++ .../src/home/Desktop/versionsticker.desktop | 9 + .../xfconf/xfce-perchannel-xml/thunar.xml | 16 + .../xfconf/xfce-perchannel-xml/xfwm4.xml | 89 ++++ docker/xfce/src/startup/help.rc | 87 ++++ docker/xfce/src/startup/parser.rc | 207 ++++++++ .../xfce/src/startup/set_user_permissions.sh | 36 ++ docker/xfce/src/startup/startup.sh | 175 +++++++ docker/xfce/src/startup/user_generator.rc | 50 ++ docker/xfce/src/startup/version_of.sh | 112 ++++ docker/xfce/src/startup/version_sticker.sh | 59 +++ docker/xfce/src/startup/vnc_startup.rc | 96 ++++ docker/xfce/ubuntu-vnc-xfce-g3.jpg | Bin 0 -> 62567 bytes 51 files changed, 5870 insertions(+) create mode 100644 .github/workflows/deploy-readme.sh create mode 100644 .github/workflows/dockerhub-autobuild.yml create mode 100644 .github/workflows/dockerhub-post-push.yml create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 docker/Dockerfile create mode 100644 docker/Dockerfile.xfce create mode 100644 docker/Dockerfile.xfce.chromium create mode 100644 docker/Dockerfile.xfce.firefox create mode 100644 docker/README.md create mode 100644 docker/hooks/build create mode 100644 docker/hooks/env.rc create mode 100644 docker/hooks/example-secrets.rc create mode 100644 docker/hooks/post_push create mode 100644 docker/hooks/pre_build create mode 100644 docker/hooks/push create mode 100644 docker/hooks/util.rc create mode 100644 docker/xfce-chromium/README-dockerhub.md create mode 100644 docker/xfce-chromium/README.md create mode 100644 docker/xfce-chromium/readme-append.template create mode 100644 docker/xfce-chromium/src/home/Desktop/chromium-browser.desktop create mode 100644 docker/xfce-chromium/src/startup/version_sticker.sh create mode 100644 docker/xfce-chromium/ubuntu-vnc-xfce-chromium.jpg create mode 100644 docker/xfce-firefox/README-dockerhub.md create mode 100644 docker/xfce-firefox/README.md create mode 100644 docker/xfce-firefox/readme-append.template create mode 100644 docker/xfce-firefox/src/firefox.plus/home/Desktop/Copy FF Preferences.desktop create mode 100644 docker/xfce-firefox/src/firefox.plus/home/Desktop/FF Profile Manager.desktop create mode 100644 docker/xfce-firefox/src/firefox.plus/resources/accetto.svg create mode 100644 docker/xfce-firefox/src/firefox.plus/resources/copy_firefox_user_preferences.sh create mode 100644 docker/xfce-firefox/src/firefox.plus/resources/user.js create mode 100644 docker/xfce-firefox/src/home/Desktop/firefox.desktop create mode 100644 docker/xfce-firefox/src/startup/version_sticker.sh create mode 100644 docker/xfce-firefox/ubuntu-vnc-xfce-firefox-plus.jpg create mode 100644 docker/xfce-firefox/ubuntu-vnc-xfce-firefox.jpg create mode 100644 docker/xfce/README-dockerhub.md create mode 100644 docker/xfce/README.md create mode 100644 docker/xfce/readme-append.template create mode 100644 docker/xfce/src/home/Desktop/versionsticker.desktop create mode 100644 docker/xfce/src/home/config/xfce4/xfconf/xfce-perchannel-xml/thunar.xml create mode 100644 docker/xfce/src/home/config/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml create mode 100644 docker/xfce/src/startup/help.rc create mode 100644 docker/xfce/src/startup/parser.rc create mode 100644 docker/xfce/src/startup/set_user_permissions.sh create mode 100644 docker/xfce/src/startup/startup.sh create mode 100644 docker/xfce/src/startup/user_generator.rc create mode 100644 docker/xfce/src/startup/version_of.sh create mode 100644 docker/xfce/src/startup/version_sticker.sh create mode 100644 docker/xfce/src/startup/vnc_startup.rc create mode 100644 docker/xfce/ubuntu-vnc-xfce-g3.jpg diff --git a/.github/workflows/deploy-readme.sh b/.github/workflows/deploy-readme.sh new file mode 100644 index 0000000..11961e4 --- /dev/null +++ b/.github/workflows/deploy-readme.sh @@ -0,0 +1,88 @@ +#!/bin/bash + +main() { + local repo="${1?Need repo}" + local gist="${2?Need gist}" + local readme_context="${3?Need build context}" + local readme_main="${4?Need readme main part}" + local readme_append=${5?Need readme append template} + + local api_base_url="https://hub.docker.com/v2" + local deployment_repo + local readme_main_file="${PWD}/${readme_context}/${readme_main}" + local readme_append_file="${PWD}/${readme_context}/${readme_append}" + local scrap_append_file="${PWD}/${readme_context}/scrap-append.tmp" + local readme_upload_file="${PWD}/${readme_context}/scrap-readme.md" + local repo_name + local repo_owner + local response + local user_name="${DOCKERHUB_USERNAME}" + local user_pwd="${DOCKERHUB_PASSWORD}" + local token + + if [ ! -f "${readme_main_file}" ] ; then + echo "File not found: '${readme_main_file}'" + return 1 + fi + if [ ! -f "${readme_append_file}" ] ; then + echo "File not found: '${readme_append_file}'" + return 1 + fi + + ### extract the repo owner and its name + ### alternative 1 + repo_name="$(basename $repo)" + repo_owner="$(basename $(dirname ${repo}))" + ### alternative 2 + # repo_name="${repo##*/}" + # repo_owner="${repo%$repo_name}" ; repo_owner="${repo_owner::-1}" ; repo_owner="${repo_owner##*/}" + ### also ensure that the deployment repo has only two parts like 'repo_owner/repo_name' + # deployment_repo="$(basename $(dirname ${repo}))/$(basename ${repo})" + deployment_repo="${repo_owner}/${repo_name}" + + ### create the actual README file for Docker Hub by replacing the variables in the append-template (badge links) + ### and appending it to the main-readme partial file + ### it is expected that the readme include template contains the following variables: + ### ${OWNER} - owner of the deployment repository and also the related deployment gist + ### ${GIST} - gist containing the badge endpoints + ### ${REPO} - name of the deployment repository + + ### replace the environment variables in the template + $( OWNER="${repo_owner}" GIST="${gist}" REPO="${repo_name}" envsubst < "${readme_append_file}" > "${scrap_append_file}" ) + + ### append the updated template to the main readme part + cat "${readme_main_file}" "${scrap_append_file}" > "${readme_upload_file}" + + # get token to be able to talk to Docker Hub + echo "GET token" + token=$( curl -s \ + -X POST \ + "${api_base_url}/users/login/" \ + -H "Content-Type: application/json" \ + -d '{"username": "'${user_name}'", "password": "'${user_pwd}'"}' | sed -e 's/.*"token": "\(.*\)".*/\1/' ) + + echo "UPDATE Docker Hub using template '${readme_template_name}'" + response=$( curl -s \ + -X PATCH \ + "${api_base_url}/repositories/${deployment_repo}/" \ + -H "Authorization: JWT ${token}" \ + --write-out %{response_code} \ + --output /dev/null \ + --data-urlencode "full_description@${readme_upload_file}" ) + + if [ ${response} -eq 200 ] ; then + echo "${response}. UPDATE success." + return 0 + else + echo "ERROR: ${response}. Unable to UPDATE Docker Hub description." + echo user_name="${user_name}" + echo deployment_repo="${deployment_repo}" + echo readme_upload_file=${readme_upload_file} + echo api_base_url=${api_base_url} + echo "curl -H "Authorization: JWT ${token}" -X PATCH --data-urlencode full_description@${readme_upload_file} ${api_base_url}/repositories/${deployment_repo}/" + curl -v -H "Authorization: JWT ${token}" -X PATCH --data-urlencode full_description@${readme_upload_file} ${api_base_url}/repositories/${deployment_repo}/ + return 1 + fi +} + +main $@ diff --git a/.github/workflows/dockerhub-autobuild.yml b/.github/workflows/dockerhub-autobuild.yml new file mode 100644 index 0000000..4690d7d --- /dev/null +++ b/.github/workflows/dockerhub-autobuild.yml @@ -0,0 +1,44 @@ +### This workflow triggers auto-building on Docker Hub. +name: dockerhub-autobuild +on: + release: + ### published: a release, pre-release, or draft of a release is published + ### unpublished: a release or pre-release is deleted + ### created: a draft is saved, or a release or pre-release is published without previously being saved as a draft + ### edited: a release, pre-release, or draft release is edited + ### deleted: a release, pre-release, or draft release is deleted + ### prereleased: a pre-release is created + ### released: a release or draft of a release is published, or a pre-release is changed to a release + types: [published] + schedule: + ### * is a special character in YAML so you have to quote this string + ### every 5 minutes (for testing only) + # - cron: '*/5 * * * *' + ### at 03:15 on every Sunday + - cron: '15 3 * * 0' +jobs: + call-dockerhub: + runs-on: ubuntu-latest + steps: + - name: Report trigger + ### "tag_name": "v1.0.0", + ### "target_commitish": "master", + ### "name": "v1.0.0", + ### "body": "Description of the release", + ### "draft": false, + ### "prerelease": false, + ### "created_at": "2013-02-27T19:35:32Z", + ### "published_at": "2013-02-27T19:35:32Z", + shell: bash + run: | + echo "Event name: ${{ github.event_name }}" + echo "Release branch: ${{ github.event.release.target_commitish }}" + echo "Release tag: ${{ github.event.release.tag_name }}" + echo "Is draft: ${{ github.event.release.draft }}" + echo "Is prerelease: ${{ github.event.release.prerelease }}" + echo "Created at: ${{ github.event.release.created_at }}" + - name: Call webhook + shell: bash + run: | + echo "Call webhook" + curl -X POST -s -o /dev/null --write-out "%{http_code}" ${{ secrets.DockerHubWebhookBuildRelease }} diff --git a/.github/workflows/dockerhub-post-push.yml b/.github/workflows/dockerhub-post-push.yml new file mode 100644 index 0000000..fb81a95 --- /dev/null +++ b/.github/workflows/dockerhub-post-push.yml @@ -0,0 +1,59 @@ +### This workflow can be optionally triggered by Docker Hub after pushing an image. +name: dockerhub-post-push +on: + workflow_dispatch: + inputs: + repo: + required: true + default: '(repo not provided)' + tag: + required: true + default: '(tag not provided)' + gist: + required: true + default: '(gist not provided)' + readme_context: + required: true + default: '(readme context not provided)' + created: + required: true + default: '(created not provided)' + version_sticker: + required: true + default: '(version_sticker not provided)' + version_sticker_verbose: + required: true + default: '(version_sticker_verbose not provided)' +jobs: + dockerhub-callback: + runs-on: ubuntu-latest + steps: + - name: Report trigger + shell: bash + run: | + echo "Event: ${{ github.event_name }}" + echo "Repo: ${{ github.event.inputs.repo }}" + echo "Tag: ${{ github.event.inputs.tag }}" + echo "Gist: ${{ github.event.inputs.gist }}" + echo "Readme context: ${{ github.event.inputs.readme_context }}" + echo "Created at: ${{ github.event.inputs.created }}" + echo "Version sticker: ${{ github.event.inputs.version_sticker }}" + echo -e "Version sticker verbose:\n${{ github.event.inputs.version_sticker_verbose }}" + dockerhub-description: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Publish Docker Hub description + shell: bash + env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + run: | + chmod +x .github/workflows/deploy-readme.sh + sleep 60 + .github/workflows/deploy-readme.sh \ + "${{ github.event.inputs.repo }}" \ + "${{ github.event.inputs.gist }}" \ + "${{ github.event.inputs.readme_context }}" \ + "README-dockerhub.md" \ + "readme-append.template" diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..04b5379 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,25 @@ +# CHANGELOG + +## Project `accetto/ubuntu-vnc-xfce-g3` + +[Docker Hub][this-docker] - [Git Hub][this-github] - [Wiki][this-wiki] + +*** + +### Release 20.12 + +- Initial release + - **xfce** into [accetto/ubuntu-vnc-xfce-g3][accetto-ubuntu-vnc-xfce-g3] + - **xfce-chromium** into [accetto/ubuntu-vnc-xfce-chromium-g3][accetto-ubuntu-vnc-xfce-chromium-g3] + - **xfce-firefox** into [accetto/ubuntu-vnc-xfce-firefox-g3][accetto-ubuntu-vnc-xfce-firefox-g3] + +*** + +[this-docker]: https://hub.docker.com/u/accetto/ + +[this-github]: https://github.com/accetto/ubuntu-vnc-xfce-g3/ +[this-wiki]: https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki + +[accetto-ubuntu-vnc-xfce-g3]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-g3 +[accetto-ubuntu-vnc-xfce-chromium-g3]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-chromium-g3 +[accetto-ubuntu-vnc-xfce-firefox-g3]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-firefox-g3 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..80d1f1f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 accetto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..9d2c3ff --- /dev/null +++ b/README.md @@ -0,0 +1,158 @@ +# Headless Ubuntu/Xfce containers with VNC/noVNC + +## Project `accetto/ubuntu-vnc-xfce-g3` + +*** + +![badge-github-release][badge-github-release] +![badge-github-release-date][badge-github-release-date] +![badge-github-stars][badge-github-stars] +![badge-github-forks][badge-github-forks] +![badge-github-open-issues][badge-github-open-issues] +![badge-github-closed-issues][badge-github-closed-issues] +![badge-github-releases][badge-github-releases] +![badge-github-commits][badge-github-commits] +![badge-github-last-commit][badge-github-last-commit] + +![badge-github-workflow-dockerhub-autobuild][badge-github-workflow-dockerhub-autobuild] +![badge-github-workflow-dockerhub-post-push][badge-github-workflow-dockerhub-post-push] + +*** + +This repository contains resources for building Docker images based on [Ubuntu 20.04 LTS][docker-ubuntu] with [Xfce][xfce] desktop environment and [VNC][tigervnc]/[noVNC][novnc] servers for headless use. + +The resources for the individual images and their variations (tags) are stored in the subfolders of the **master** branch. Each image has its own README file describing its features and usage. + +### Image generations + +This is the **third generation** (G3) of my headless images. The **second generation** (G2) contains the GitHub repositories [accetto/xubuntu-vnc][accetto-github-xubuntu-vnc] and [accetto/xubuntu-vnc-novnc][accetto-github-xubuntu-vnc-novnc]. The **first generation** (G1) contains the GitHub repositories [accetto/ubuntu-vnc-xfce][accetto-docker-ubuntu-vnc-xfce], [accetto/ubuntu-vnc-xfce-firefox][accetto-docker-ubuntu-vnc-xfce-firefox], [accetto/ubuntu-vnc-xfce-firefox-plus][accetto-docker-ubuntu-vnc-xfce-firefox-plus] and [accetto/ubuntu-vnc-xfce-chromium][accetto-docker-ubuntu-vnc-xfce-chromium]. + +### Project goals + +Unlike the first two generations, this one aims to support CI. One of the main project goals has been to implement a simple and cheap *self-containing* CI with minimal dependencies outside the project itself. There are only three service providers used, all available for free: + +- [**GitHub**][github] hosts everything required for building the Docker images. Both public and private repositories can be used. **GitHub Gists** are used for persisting data, e.g. badge endpoints. **GitHub Actions** are also used. + +- [**Docker Hub**][dockerhub] hosts the Docker images and is also used for building them. Public or private repositories can be used. + +- [**Badgen.net**][badgen] is used for generating and hosting most of the badges. + +None of the above service providers is really required. Images can be built locally under Linux or Windows and published elsewhere. + +Building process is implemented to minimize image pollution. New images are pushed to the repositories only if something essential has changed. This could be overridden if needed. + +### Changes and new features + +#### Naming scheme + +Unlike the first two generations, this one will aim to use less Docker Hub **image repositories** with more **image tags**. For example, previously there have been two Docker Hub repositories `xubuntu-vnc` and `ubuntu-vnc-novnc`. Now there will be only one Docker Hub repository `accetto/ubuntu-vnc-xfce-g3` containing tags `vnc` and `vnc-novnc`. + +#### Slimmer images + +New images are significantly slimmer than the previous ones. It's because that the most of the packages are installed with the `apt-get` switch `--no-install-recommends` by default. This could have consequences, so it is configurable. + +#### Fewer and more flexible Dockerfiles + +Image variations are build from fewer Dockerfiles. This is allowed by using *multi-stage builds* and *Buildkit*. On the other hand, flexible and configurable Dockerfiles are slightly more complex. + +#### Concept of features + +Flexibility in Dockerfiles is supported by introducing the concept of **features**. These are variables that control the building process. For example, the variable **FEATURES_BUILD_SLIM** controls the `--no-install-recommends` switch, the variable **FEATURES_NOVNC** controls the inclusion of *noVNC* and so on. Some other available features include, for example, the **FEATURES_SCREENSHOOTING**, **FEATURES_THUMBNAILING** and **FEATURES_USER_GROUP_OVERRIDE** variables. + +#### Optional overriding of user group by `docker run` + +Support for overriding the user group by `docker run` has been introduced in the second generation. Please check its documentation for more information. This feature is now controlled by the variable **FEATURES_USER_GROUP_OVERRIDE**. + +#### Different use of version sticker + +The concept of version sticker has been introduced in the second generation and later implemented also in the first generation. Check this [Wiki page](https://github.com/accetto/xubuntu-vnc/wiki/Version-sticker) for more information. However, the usage of the version sticker has been changed in the third generation. Previously it has been used for testing, if there are some newer packages available by following the *try-and-fail* pattern. That was sufficient for human controlled building process, but it became a problem for CI. Therefore it is used differently now. The verbose version sticker is used for minimizing image pollution. The short form of the version sticker is available as an image *label* and a *badge* in the README file. The version sticker badge is also linked with the verbose version sticker *gist*, so it is possible to check the actual image configuration even without downloading it. + +#### Image metadata + +The image metadata are now stored exclusively as image *labels*. The previous environment variables like **REFRESHED_AT** or **VERSION_STICKER** have been removed. Most of the labels are namespaced according the [OCI IMAGE SPEC](https://github.com/opencontainers/image-spec) recommendations. However, the `version-sticker` label is in the namespace `any.accetto` for obvious reasons. + +#### Simple self-containing CI + +The third generation implements a relatively simple self-containing CI by utilizing the Docker Hub builder *hooks*. The same build pipeline can be executed also manually if building locally. For example, an image can be refreshed by executing the `/hooks/pre_build` and `/hooks/build` scripts. The script `/hooks/push` will push the image to the deployment repository. The script `/hooks/post_push` will update the *gist* data and trigger the **GitHub Actions** workflow, which will publish the image's README file to Docker Hub. + +#### Separated builder and deployment repositories + +While there is only one GitHub repository, containing the resource for building all images, there are two kinds of repositories on Docker Hub. A single *builder repository* is used for building all images. The final images are then published into one or more *deployment repositories*. This separation allows to keep permutations by naming reasonable. Not all repositories must have the same visibility, they can be private or public as required. The same repository could be also used for building and deployment. + +#### Separate README files for Docker Hub + +Each deployment repository has its own README file for Docker Hub, which is published by CI workflows after the image has been pushed. The file is split into parts. The part containing the badge links is separated into a template file. The final README file is then generated by the script just before publishing. Re-publishing can be forced even if the image has not been actually refreshed. These README files are shorter, because their length is limited by Docker Hub. Therefore there are also full-length README files published only on GitHub. + +#### Based on Ubuntu 20.04 LTS + +The current images are based on the official [Ubuntu 20.04 LTS][docker-ubuntu] image. + +#### Using TigerVNC 1.11 + +The images use the latest [TigerVNC 1.11.0][tigervnc] server, which has introduced some significant changes in its startup process. Actually the images implement the newer TigerVNC nightly builds, that fix or mitigate some of the issues. + +#### New startup script + +The startup script has been completely redesigned with the help of [argbash][argbash-doc] tool and the image [accetto/argbash-docker][accetto-docker-argbash-docker]. Several new startup switches has been added. For example, there are startup switches `--wait`, `--skip-startup`, `--tail-null`, `--tail-vnc`, `--version-sticker` and `--version-sticker-verbose`. There are also startup modifiers `--skip-vnc`, `--skip-novnc`, `--debug` and `--verbose`. Also the utility switches `--help-usage`, `--help` and `--version` are available. + +*** + +## Issues + +If you have found a problem or you just have a question, please check the [Issues][this-issues] and the [Wiki][this-wiki] first. Please do not overlook the closed issues. + +If you do not find a solution, you can file a new issue. The better you describe the problem, the bigger the chance it'll be solved soon. + +## Credits + +Credit goes to all the countless people and companies, who contribute to open source community and make so many dreamy things real. + +*** + +[this-github]: https://github.com/accetto/ubuntu-vnc-xfce-g3/ +[this-changelog]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/CHANGELOG.md +[this-wiki]: https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki + +[accetto-github-xubuntu-vnc]: https://github.com/accetto/xubuntu-vnc/ +[accetto-github-xubuntu-vnc-novnc]: https://github.com/accetto/xubuntu-vnc-novnc/ +[accetto-docker-ubuntu-vnc-xfce]: https://github.com/accetto/ubuntu-vnc-xfce +[accetto-docker-ubuntu-vnc-xfce-firefox]: https://github.com/accetto/ubuntu-vnc-xfce-firefox +[accetto-docker-ubuntu-vnc-xfce-firefox-plus]: https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus +[accetto-docker-ubuntu-vnc-xfce-chromium]: https://github.com/accetto/ubuntu-vnc-xfce-chromium +[accetto-docker-argbash-docker]: https://hub.docker.com/r/accetto/argbash-docker + +[docker-ubuntu]: https://hub.docker.com/_/ubuntu/ + +[argbash-doc]: https://argbash.readthedocs.io/en/stable/index.html +[badgen]: https://badgen.net/ +[dockerhub]: https://hub.docker.com/ +[github]: https://github.com/ +[novnc]: https://github.com/kanaka/noVNC +[tigervnc]: http://tigervnc.org +[xfce]: http://www.xfce.org + + + +[badge-github-workflow-dockerhub-autobuild]: https://github.com/accetto/ubuntu-vnc-xfce-g3/workflows/dockerhub-autobuild/badge.svg + +[badge-github-workflow-dockerhub-post-push]: https://github.com/accetto/ubuntu-vnc-xfce-g3/workflows/dockerhub-post-push/badge.svg + +[badge-github-release]: https://badgen.net/github/release/accetto/ubuntu-vnc-xfce-g3?icon=github&label=release + +[badge-github-release-date]: https://img.shields.io/github/release-date/accetto/ubuntu-vnc-xfce-g3?logo=github + +[badge-github-stars]: https://badgen.net/github/stars/accetto/ubuntu-vnc-xfce-g3?icon=github&label=stars + +[badge-github-forks]: https://badgen.net/github/forks/accetto/ubuntu-vnc-xfce-g3?icon=github&label=forks + +[badge-github-releases]: https://badgen.net/github/releases/accetto/ubuntu-vnc-xfce-g3?icon=github&label=releases + +[badge-github-commits]: https://badgen.net/github/commits/accetto/ubuntu-vnc-xfce-g3?icon=github&label=commits + +[badge-github-last-commit]: https://badgen.net/github/last-commit/accetto/ubuntu-vnc-xfce-g3?icon=github&label=last%20commit + +[badge-github-closed-issues]: https://badgen.net/github/closed-issues/accetto/ubuntu-vnc-xfce-g3?icon=github&label=closed%20issues + +[badge-github-open-issues]: https://badgen.net/github/open-issues/accetto/ubuntu-vnc-xfce-g3?icon=github&label=open%20issues + + diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..db5e977 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,4 @@ +# This is just a placeholder. The actual Dockerfile will be set by the hook scripts. +# Having this file allows to keep the default 'Dockerfile' value in the build rules on Docker Hub. + +FROM scratch diff --git a/docker/Dockerfile.xfce b/docker/Dockerfile.xfce new file mode 100644 index 0000000..02b6995 --- /dev/null +++ b/docker/Dockerfile.xfce @@ -0,0 +1,275 @@ +# syntax=docker/dockerfile:experimental + +ARG BASEIMAGE=ubuntu +ARG BASETAG=20.04 + +ARG ARG_FINAL_STAGE_BASE=stage_vnc + + +############### +### stage_cache +############### + +FROM ${BASEIMAGE}:${BASETAG} as stage_cache + +RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache +RUN apt-get update + # --mount=type=cache,target=/var/cache/apt \ + # --mount=type=cache,target=/var/lib/apt \ + + +#################### +### stage_essentials +#################### + +FROM ${BASEIMAGE}:${BASETAG} as stage_essentials + +SHELL ["/bin/bash", "-c"] + +RUN \ + --mount=type=cache,target=/var/cache/apt,from=stage_cache,source=/var/cache/apt \ + --mount=type=cache,target=/var/lib/apt,from=stage_cache,source=/var/lib/apt \ + env DEBIAN_FRONTEND=noninteractive apt-get install -y \ + jq \ + nano \ + psmisc \ + sudo \ + tini \ + wget + # && apt-get -y autoremove \ + # && rm -rf /var/lib/apt/lists/* + # curl \ + # gdebi-core \ + # git \ + # inetutils-ping \ + # lsb-release \ + # net-tools \ + # unzip \ + # vim \ + # zip \ + + +################# +### stage_xserver +################# + +FROM stage_essentials as stage_xserver +ARG ARG_APT_NO_RECOMMENDS + +ENV \ + FEATURES_BUILD_SLIM_XSERVER=${ARG_APT_NO_RECOMMENDS:+1} + +ENV \ + NO_AT_BRIDGE=1 +# LANG='en_US.UTF-8' \ +# LANGUAGE='en_US:en' \ +# LC_ALL='en_US.UTF-8' + +RUN \ + --mount=type=cache,target=/var/cache/apt,from=stage_cache,source=/var/cache/apt \ + --mount=type=cache,target=/var/lib/apt,from=stage_cache,source=/var/lib/apt \ + env DEBIAN_FRONTEND=noninteractive apt-get install -y ${ARG_APT_NO_RECOMMENDS:+--no-install-recommends} \ + dbus-x11 \ + xauth \ + xinit \ + x11-xserver-utils \ + xdg-utils + # && apt-get -y autoremove \ + # && rm -rf /var/lib/apt/lists/* + # x11-utils \ # adds 200MB + + +############## +### stage_xfce +############## + +FROM stage_xserver as stage_xfce +ARG ARG_APT_NO_RECOMMENDS + +ENV \ + FEATURES_BUILD_SLIM_XFCE=${ARG_APT_NO_RECOMMENDS:+1} + +RUN \ + --mount=type=cache,target=/var/cache/apt,from=stage_cache,source=/var/cache/apt \ + --mount=type=cache,target=/var/lib/apt,from=stage_cache,source=/var/lib/apt \ + env DEBIAN_FRONTEND=noninteractive apt-get install -y ${ARG_APT_NO_RECOMMENDS:+--no-install-recommends} \ + xfce4 \ + xfce4-terminal + # && apt-get -y autoremove \ + # && rm -rf /var/lib/apt/lists/* + # && apt-get purge -y \ + # pm-utils \ + # xscreensaver* \ + + +############### +### stage_tools +############### + +FROM stage_xfce as stage_tools +ARG ARG_APT_NO_RECOMMENDS +ARG ARG_FEATURES_SCREENSHOOTING +ARG ARG_FEATURES_THUMBNAILING + +ENV \ + FEATURES_BUILD_SLIM_TOOLS=${ARG_APT_NO_RECOMMENDS:+1} \ + FEATURES_SCREENSHOOTING=${ARG_FEATURES_SCREENSHOOTING:+1} \ + FEATURES_THUMBNAILING=${ARG_FEATURES_THUMBNAILING:+1} + +RUN \ + --mount=type=cache,target=/var/cache/apt,from=stage_cache,source=/var/cache/apt \ + --mount=type=cache,target=/var/lib/apt,from=stage_cache,source=/var/lib/apt \ + env DEBIAN_FRONTEND=noninteractive apt-get install -y ${ARG_APT_NO_RECOMMENDS:+--no-install-recommends} \ + mousepad \ + ${ARG_FEATURES_SCREENSHOOTING:+ristretto xfce4-screenshooter} \ + ${ARG_FEATURES_THUMBNAILING:+tumbler} + # && apt-get -y autoremove \ + # && rm -rf /var/lib/apt/lists/* + # ristretto \ + # xfce4-screenshooter \ + # tumbler \ + + +############# +### stage_vnc +############# + +FROM stage_tools as stage_vnc + +ENV \ + FEATURES_VNC=1 + +### 2020-10-03: nightly builds fix some TigerVNC issues (e.g #1097) +# RUN wget -qO- https://dl.bintray.com/tigervnc/stable/tigervnc-1.11.0.x86_64.tar.gz | tar xz --strip 1 -C / \ +RUN \ + wget -qO- http://tigervnc.bphinz.com/nightly/xc/x86_64/tigervnc-1.11.80-20201209gita3d7d7d4.x86_64.tar.gz | tar xz --strip 1 -C / \ + && ln -s /usr/libexec/vncserver /usr/bin/vncserver \ + && sed -i 's/exec(@cmd);/print "@cmd";\nexec(@cmd);/g' /usr/libexec/vncserver + + +############### +### stage_novnc +############### + +FROM stage_vnc as stage_novnc +ARG ARG_APT_NO_RECOMMENDS + +ENV \ + FEATURES_BUILD_SLIM_NOVNC=${ARG_APT_NO_RECOMMENDS:+1} \ + FEATURES_NOVNC=1 + +### using the same parent path as TigerVNC +ENV \ + NO_VNC_HOME=/usr/libexec/noVNCdim \ + NO_VNC_PORT="6901" + +RUN \ + --mount=type=cache,target=/var/cache/apt,from=stage_cache,source=/var/cache/apt \ + --mount=type=cache,target=/var/lib/apt,from=stage_cache,source=/var/lib/apt \ + env DEBIAN_FRONTEND=noninteractive apt-get install -y ${ARG_APT_NO_RECOMMENDS:+--no-install-recommends} \ + python-numpy \ + && mkdir -p ${NO_VNC_HOME}/utils/websockify \ + && wget -qO- https://github.com/novnc/noVNC/archive/v1.2.0.tar.gz | tar xz --strip 1 -C ${NO_VNC_HOME} \ + && wget -qO- https://github.com/novnc/websockify/archive/v0.9.0.tar.gz | tar xz --strip 1 -C ${NO_VNC_HOME}/utils/websockify \ + && chmod +x -v ${NO_VNC_HOME}/utils/*.sh \ + && ln -s /usr/bin/python2.7 /usr/bin/python + # && apt-get -y autoremove \ + # && rm -rf /var/lib/apt/lists/* + +### add 'index.html' for choosing noVNC client +RUN echo -e \ +"\n" \ +"\n" \ +"
\n" \ +"_;Hz+qD3PDhbl zUu)3K%Qeh%{v+_bL`heMR7Jx<7iNbs`h@zMCx{ zS9HhCw{G8?h#v=9n(pj1rMJoTAc*v}pBvn#SNY8`cvn&AI#UgN*X_!yfgg%*urd>_ z?9w pEk0AGABr=piVMuGw(8i{{w~yF z;Aow5zlde{`E%AZVG;Gl`d=tOr5O<}FeUdWAvPmMEfuSw2o_i4&>Apa{t*$`5#%on z 6IC7mLWFE+IMsRpUMQL^kw3GtqJQ`yn z>Z5fF>oEofvuGqti)>*#z?zfOuHg02jH`Vj#MfYYz|+Y={~uNsJyEY9HGrB;2 F;{DT>&``7NbET|AP42IOji0Il*Vlq#daTYs}Ua(M?FDls&8%&Fi$ zzW*5EmHESy1uZ4c@l?aeaqr8yUWsY&9az7TlsC=KYVKW_)gO8OySFvE{fjqNA=YPQ zrjCg!e}1rxY&`Z*SsjmOG`SvlBSJh 5h;?0vbve_q%3W+(X4$-paFQYz11a3XH zZ;SDci=JuD!c8Z>zP|f#jw=lNJatD>ipvNj5JHcHaB04uu}vRr5hQ*0a%gL_3+ %PBh^N*wJ*?x3S7}dO*B_Za)J`5 zAOi$xBoWWVunUI}Fw|76;l&uwdlYIuz>l?gp~4A#{PqEVeWhf{wfu=8jSP$eU^@d) z|GuKVd=8A;?<2!%4*T^FQRSf8i*i OApaOC*C<0CkTFfE}-6v2> z(rNO83V`9P1^0SF1!IVw8#HL}f_#vGa#OUY;j{I`;P(o=!z0;xXi^KZzQC=)Zo_b3 zOv$w>XjO ~kqXm3}nuAUw6iNVjPB1{TRuEc-b3rEL `VAG!6ghWr+y?(iPT5S(uzP);eV&w_fz7xnBoW!#pl8XDeij;Svl znzh^{^G?L@XH;Z1(mH=pmsgi&8*aL3d@e3eul(`dqCF!;kvrKwCa>4+cqh+va{Pa^ z_vP_WzVH51Dn)1^StlV|sF0 >POLk%Gl M7Qk7tyrc}w#o zGvzv``UvTI3c(ioFYdf#mM$CGXR>+uE~g}ew=>diN>Wyu?T+aFZ-sSMYhI=a>Inyq z-+CD2N)7Q!mWt-kq-p8bR(<2i_GQ$3l)S7*le??XHcE7Yh-XMSHuzN*-Ei&Y_!AXo zL)QbW=Y$Fc>;fS6N%LrP3rEh&>G}Q)@=8uikt~f&@l$%@C!a~=Q}3^zqmsxC2n}lu zeZzf0epe!}H@&+AUNaD3zyb~nB~6iMZEYI6fOrFh3$P;Hec|D!Aas4VpO8F29u>eR za71`Xd&jk9mn;KoZj?{PnPb6$RUPX0SxEr7QdNgqp)0xx$Rtrd$%M%PNx6yZdxb;2 zB0Ajd?<3XlEo?uC`*+y6k566DaQbyd0ATe`oF|={uuaU}dOIjK>Z{;-#B$sxm3hGl z*+&kvLuU~s*l4a7m_cMy^dkqBlrkd-1xZ}&AZ`%tXUZLDn?(?1*l1RBQtIj7zb&C5 zWRw5dNh!a3QSkNd<+w)l<}|+bF1^e*o-#{lxfPmEz1Rc%Y-54Ge%b#_F^jBF6PoBM zxV6H)90!zH-|sLKh2w4ei>=px|5lL@#7|<@TN3WlU-5pdhHr(MuK;z`i`5Oe+=`fg zBl}{`2iy-#KQRD8K~Y@9VJA|d?egKWLe2g}*QBi#o{KnWJ2m=+!4WmJtynmI3X~Z) z3*zRQHA%%CyKOHoE4TI(nn;J%TjDpbAeOrjo0Dpw)?BCLvQ`?xDw?=Kivl@k;h@1e zEUo-3Q|xx+gthJTL>f~18u$2Zdqp`{|JgH8GjR2s&z9@E1zOe$p4bRHF=uS-=5_dT zA7XPx9hLes3(8|M($8mB6>0{qzN9R#L6${QmLQ!Trz^F=v7(N^%XtvwQd>)d@bmPf zia@UL@Hd+VSi-tLag!EnQ9#NCZD$hjO-^?22H*hVFi41)bsSn=+{xr)ucWAode={M zKM5YYMzC)dJ24^%nlp~_`Q)2YnYQ)&T0j5KYZ14;8hn^cmg)u0+&_v8-zk#Ew&5*4 z!q!Gsdac14kK1mEWj+uGUqIkV_-3R`241PDQZ^v*cpoB>0-4_jdi)b&eL;O36pFUB zQQ$2s1?mdv{x1pi`Pk)Unk@n?DAi72{ITpM!3=2PD|{2jy=j$2AXEVg{=Fc40+jle z$GouYSH?|;pH~HR9jQT`>YY%5-jAx()}~eP8>H%Qf~= QfY8&U~R%ABR~}m0#)Eq8(F5XYhK_ouwjDBeaE2Xb@Ct2Dpzzj zJPk4hK7!2yqykA~+B@G@)W;&W3;)CQ6(~^fS4lbq)19tt _@K^0#5@Rr2Db!8 z>{O;hFtb&Bi;o+~QPjfbT4E>WhKNMcDFAT*LqY&A?e$ftHiF|lO{8RlCW-P%5KjQ3 z37bX~#`c{@F5|&Sf CnW|cCBqcO5sk$_Gu%2l}&8R22F2(HaEce13OJYCDZ9_D%24nelRUaPXs4r z*! kXlSPt04p}H7HkobiwPg3Dw PRmNJl6Q`RLJ}v z(it;>nub`zl3E?Xu}Kpn+29clmdzh`0b3}ku~44 UN0yukufE`urZGMXf^(pX1td;#C`41;n2;y2npb2Oc9x&VfgDfM( z0W1oO@6L&=)Z938!jtVQa8CdNjp;9e=9dK1xX?}Tb5+@L2209oingqDl4w56yDge4 zaC1>8Dbl4xX>U?|igPGd4nAB(PC@H_y23qoT>T90g+_t|hN4Jeb~fP{#&Ywzdf&cl z;~sRO636&+JsLa?h>6c@iR@F7QBl0{Cd%AE_@fC~7 7 zV?g`UH(^dwf{tZI0l;m5tof#=e2U`zCG%z78r%D;x3t=>b#PpWHdv_ey{{9rPe|MU zqV4`nBWDv{CX0YOtWR9gt}jPDXS=$1oMYF%4mAgzdNRwtXB0ACis?L;boH=ODP`bI zS$W~`L{vLxP1pN#RoslBx7q6%;3a`&_fdydn$6`x_m|{(Bk_Bg1U%>QUOC-~2)KC; znWCh}AZKpkK8EGpgi@RCX$|?kpM+#-yF%DM^|K%J`D#74g(~jc 8d#EZDKz4)rHl81`X*eB}pnELFid*5PKf mhf z@O!*FH>}UjPF`wFu1xXaRUVygnVEnGz*#I_Pf!5Z5+I^LlObv5K-&SDxp!zA<1J1Q zeDGTOnrVFEt{t7-lO*Z2m{IK}VWPJHwBeL^B3@Ws119WE!drog53W${0|*yM#RqT} z&m(o9TZ0?7WkqkGFad4;5lMF3Mbhg@_<+oHX@Gz3S5VLZC8z^g64v%3-`TyQc|7sL z)j*T=e(Vdhf6lW2E(0m$JOJ)`;So&2#(?U--wc>`pK`~?zW9Zb{`tSKI)GKG-f-va z1k*STKzEQgvE>A9?QcbfcLUEN-3=3xn-S|4P`T-ZF&j(U0C=K>&^GLeSRE(9o(g5D zB%IS{8|M_!&?%8^vkGpF+Pp4td5EptizR_vQfg5Ry=MMdIGKy%U|Wj3ro5DwS_UtF zUWeZlv1XMoO7TQf+hFurub4?FU3;#iJ^#@&nH&CH%4uww%`JS9xebE2k9R#g*f2 z_0*us>Vo%(L`dCb*OfFc`pwv=@z-#Bcde$kY6i*$FO*hf_bgSrT7|_|4qJ}caMY(C z3b&j!C}*ZgQn$EjpnZIPCerE_%7ahVdqU~ZwMId5+pWfu35L&gdgifNpJ5u;P4zjY z5eh}Ojk&q=?=jzr6BWkBtF_M^J33tOTu(YNNB*=JLcrv6tuxnso;U4^Il)Ynt&kHZ zLFd|JP}vQ%%|QPne9)IOLM_W}xsH!p)c2^`(%$=~GL=0CH^5j=bse$NtEHUonPt^5 zGhx6eNoi1Z?@@T*Ji70G68bZZ`5VSQ$f$xfjWd0gDkq&H`=fx7U16%nzRLGa$|KHP zrN|!aXIgI&E>2nQFC+OTig0mBqo-V@K{_65Ji?nU;Wbu$;=?aK?e{m{%NNR4R3SFq zczIYLk5W|I?AT!Caj9EZyR^pa<|7M@Wjdt^+%RfSI{Ss}Cq GCqH2{m^VoSJEYFYow%D3pu%AG zk*2WGp*HnMnV;$zOR{iiH3^ziJ<9{;Q6d`^r=YpQt$iVR{G7W ZsU@h|1cSI z+(ZERLQDv7-~;iLle=@%rcwx$EjU+fbwt_`KPtL6FSg&BM{sx)c&p(39gyAktYw$H z^y~JW?gFbYSZjfminPGOK<6p3ffbenpEAk-{E1{J@VveUB)kRyDrxo04gIlldizmv zs_q2<=xfsDM79I*jo=OMW)zYJB}U4~?tAg%)U!y^8vCT}uBR-FC53clr)*VIP(Kw| z>=So`H>b+BJqSV>fgz0SnyK*4AX0!SfF>D{tSE`F?Nyj$FXKFOR9LMq_z}f*;NJ1* z?)H!rJ_=B-avrd$kXG)#TMWQ?Rbv-$kRpY%Fn|F7oTGqA3^*x)aqusYd~x}YqeY&y ztn1BhABkg{^}}U)i+9^K5BedZxd7!1h-m3UKQXA#9So|Ngh8>AFsN$ay<+~U5&(~9 z4z)4Xc9v)*nbBkJ79N%7hQ0Nb?#JAGu8A0y0(2jNLt6`2g4XTRO2>hlv|Xau#VaET z$1ku*a@rvlFlNZ*+Ib=lN#xC2$uMu$eH@=-7bbSc#v56gdfZP7e%i#5_k~`^XroxJ z|4OKu0l64y9bw!9AbVh_BH5UL5U@SXfh0hh;lVHVn}UrS?7d)B0V@V0Fpu&8>|R(6 ztT T5Z5v@_f9}{a06yh;O2xJ_e1W_{#r7IV7{KDByt1Eadl4b6PGHz< zPXOBLoi$~<83#ys>m!o!_UtZT(ozDW7Bm51ufpDsC}g%%NoBDl?- xt; s9!83E z(smEoj(fu5tckKpT*MNf#{+YdHkXeB6URbXXqLLFXl4D>^r?0OYEV`8rxpE}g%_**sI(PjI$by<~Q1CPmN z=r|bXy)NHjFwll$#n!k>!p(Rbc!079!1tM{U-Pa`)K6fLOZU)B6;D0lMma~EN57LLyl{n^uk!UrF}-K Uiasj${*y*Pz&(ac8RDUS_{MRPdhPWc zHZoari+8zZ_{&As+bY3o)lKX8XhYwO{%LJ@OC(2H_4A`2F$?P%yvsBPZc;)=`g1j2&LZQSj%<0Y?=TYf@B;;aOnaf` z@ok+wb5Pz HN&)B)^N0E#`nZhiuk}xaOFRTc2`u*P4v%*h0PHl7(-2qU5 z^$3~$32os`dW27%3V!n&(BkU1`T=r{N8C15kyqWy|CtT_3op|EAP>L~{~_BCd`@E= z^(fp^^*3?{-$vk`V&}6}!qzB*+cc5C66Alubhc#`_KLDHYwv%+cBsrD;=>vMq58RH zz4bNY70l}g*n~4EM1Ji(0389k$+J{eu3#pl#`N>IR3`vqBu7a|qLfb00dNVG3QDOX zl_J$iPFP0+WYV^*TwXpBO~N;~AyN6Y7l?^mXuT)tW3_@3n+W}Hh!mX*urbNF?eetu zcn8P*KuagpQ9A(Z3QzCTV37P1o+SacB(yjB1x {di8Nn0OD!Ba^aF;D|BXza zE_aDfd Di&ns_yVB$r};%B9=9896I{h$?jKh3E@JX-CXz z4JmTPJQILUC*C7BMgUo2n#cx ($RYXJ_0eYSh ziJxNyL{$+u%oy6~;&+$}8mIFWcy0S_9IgEGi~WD;7K%kJCqZU6@xBh&CRD$!&8wJK zYS%jiISrJ*U9Ng8^!UZ0n4}_Fow3egK`TL>?oV5%0!u?thkMM1mM8%(n#n^VEX>i$ z1xw$NpJRm~tCJg0w>%{*k$7B4{)l(;&H>Lp5Kd5s{SHI-B51~V>(-LC&VC08z(q>m z^sZIg39fDq4XG*s+=3CXIEoZrBA|Fzd2df~#LwgLQWGtxhkMln*bJ!((;&Uf8fX@| zVGIfbfl|rD&hM~91nxVKDfH4&-u*-%UyRlfOgE_t2+N=jG_DJy(*#Y-xX%+i&{knk za|(o9Tf~4337$ KAy7lUM-2ncyIN 9qTHI>xj#yMl(3hROM>bJx`~BJfWia> zykf`b0q%bjD00$tcd@tLkU}$-BZq+64i*JI4L0-fz+j~A)CB{t&b;g*FLHUh{mbMX zr}T-t&BOHCR>=~~*9xX$Zh2fX1Y4$$H?l?^9%!tO=`B-gG+naGMEM^!qp^wY9jL6D zrMEu)=-Slt8f#WEg&9|>3DXJOwJF*2{M1B?L=QTTOZ Z{D#c8Z%KM{e&Tl@9}cSuHO}*O;0QpMxO~xa5lPNBymCKtKG;BH z_T;^spaFJazlr?;SBFBEySWlv4p$pnFU)_2^jYKHJjvfYJYZ(0ujl)<=&hE$*-5yC zQv1nZ$`j4(yydRXY$Bc3G?#~D_NE)Ep6795Z _v)-(X1>|X6&-}0!O(k zI-Ouuw$$g&9Y}LnbaFKuyuvGH!SA$u*q&c{p0W4HF+Pj63hqJ`o;OXDK22w644o^Q z71AEwJC6~T7x(RQCiIwiOP{> i9_nr*KWk+ZUs9gGd~hYhoj|Rz=U e|T{6<^rCVqx0anSLu+oN||ko{mir>bR?&UTcP5XtzXr`=U^q91YN& zv$DRN1Mj-?V(VW6r24DwR%E`|_AHK$OauObG=;H45&@CCinB&*{Fg_BBPiazdz@>( zrxh8d^L6drD)e$gi4}PdF1uyvAmK#tn1!bOpvjZzodyV^bU1cLys=oNfRlK`E@l8< z-)!*i^3NSh%Fc;U?XXJESi=_xah#nKV|wvO2p5^9@`R`Gsl0fB!Ke^S9*rq|+|1&f z66KazBP(EHyU;!(kY{S&$ffZxt*-c3BU7KSx%i2<;^Jg1 09DCyGhK+C zq*r2eW`93Y#&x~>j0#N{ZR+s@9H%o%b@uEQ>W?{)MR7b`X=aXSXz{^*Nz&!^q~7%M z66gStvd78tHbw#&T=@khk=#$_;S?;7sL;yJtEm Mfh6oIa#SVmJbD{3CphyhW#)h_Yc`rF+V!1&AxalO7v;Qs!RO&X-1X1 zmQR#huVe bPBX4sV3q idR8aueQNe{}DHP4{u}ItA~qT_YdI`Ufv9T!(Qo-+F{fGgj%GT`84OMizWC>ie8& z0`GlxlZJnA_oI-Lo*(+lzXe&meCPkMKrMiEwbQFwJ53O!dt;(nH9=Ww`aM4Yj9ukm zB!Blmza{6d+QMDsQ-JA!1UWVDKu*vYj{`uQfI*#vIDxMu#K~U{XR{(_0Wk3Tb3gY> z?RJ1pG5p#vjj+n34O6flNAYvVG-e}t>>f1_stk;43->$isdgT%U=Y{l$Ni4#N?(}= zaC?3GSM9gI(6HQ9VGdq#@qhA)eYan+*{@f;L}!%t?K^Dg;I>{s@VZgsj*$T@*U0A! zA|#h~S~b73dN23V8U+9tb%%3_y9S);?sxXmpFNRhv5KSl-SNJw6=Jd+UmS#CAOCa8 zr+=3R>R%yIj9-p;IRd%b3nH%AWz7a}nk%Bjg62e|+4t^quHA<^5R2u^Qrk4MdOtle z>FzJ % z-(!ybg1?i#tuCiO|AU4s*f&|6F#DuC-;w^PUIp=;W 3*wZrrR1+HJj; z0oq-@wLdG`+lsd>LzYjTt6^!&HKya;xPowMfqftL6LvJqTkk4n*es8Vf`Kij(W&?) zrSDN(PRtW(=anqhtd!NBCq$MGqub9p(^KU-sob(6U5@c)xT 0a>$=A&uj&p(y{~p&LL(&ndD}7!My*KbR@K-({@T!0!IQ z1Ny8yI$SL~1E-$(XXID+=T|9v>kOYN0bx9U2ngfP(&&&X0HCxg*s@U> kEwxALW_oOr)wcHPy{T?oukLO+}JdM^QOe zo0drx1ewO;wP&&zW^T|FLw)cq*XqTrs+TMKo08&+%G#LkAK@8jC2JR(LiEv9>6m?i zp3+M(hU%I#W#;-SvmP6(iAk{A2=Xq8e4+3{SE5j tTMy(Zx+c5kdKFpro>9DmHj<`<-}wGX^wolhAVY`c<3xT; zTT$x0o*SHZ`e*w)`WPf#L>+?(&5@H?af0s0amwo)-;DMlYW4)YAPAw`il&D=Bs5>1 zXN>+_G{dR&jHZG18*n-#=pY4`3X?)cjPt;`oz1kdr4kcgyi?=1LbP&1p?29jMBOw- zt_q9Eylb3YSyp;oq6Zhtbt5m)d>%VUW?+53f_s@4^RnsPfJRsm_4II~*ILvUMM~7Q zy&(rDi^kQ0zR+ML`84zwzDAAE7BI%2lCk1?d6X}V*FCO4 aDM%A^O%wYjjDVp 7L(We( z0QLyZivgC+Cn|;u+By4@Qp}q9OVb$kbbW`FTz}*k667g1?YF_`aqf%@UFqrhqjU}0 zZ7O5L6%!4f*Fz!*l3d;VQcy(S*^SFA-fTwqtDPNm>TD5yKSq{$OX;>wrkmyhT|$OG z&hx6*t)8k`)f1J^ltmx+j0K=;OM=R(b{U4BMCT@TzF)_#7Cc|R@lk}kV+^BIipZ)4 zK|b^1AeI&cxBa>PsE-0Km}k-5TaF~JHl2C)#+8Yge5K9W@yrJ*lC_JTvhG?)+`H9# zlbTo`_!WCc_!1Rx5zgcRB4_H_AAV$YkYH&4B`FG$Z$u^OXgBcjr+ePr1s7R{*A_+n z`0eMeTz6`!!WlDT7B-&WaF~Y3ENMTanIDugIj|dU9Bw_9SM|b(6;3Jfd?=||CW~BF zyZS1Pao1}PK7Hpe1+qchp(jrU?1kOh1>7gy?|fdp_u2A~oL+l&pSdbM#dm&cUT&e& zzuC5{*rCk!nramKEsIKfWLvtVzEXSor{bz_Rw>BjYVPun{b<=swukN&){39XkB#H8 z{kVq0W>q)EnHiqPhYKsYvbZvE<>tNj`+V(iqYZudDb~~jA6UmIIx=^+nJhGp4YDuJ zWiy(K9uD>XC_3==s kn5pHwe$GPP=ipmm>WOkni7gxM?p&hs6Ziyw;Owd}zD-6YbdLmmivoRtPA* zs&Bgf+4qb-)p3LbD{-PS$@d;)5xmFp5GypE?flZn+^%5^bc7T0n?Iuu2aijNWm&Z7 zVBotm`1@}q)|i}WwLj(O2MR^xUp1-@zBESE)ENt#$^r%$JSJAnbIoQ&Hi`znuOI5> z1k$wD!{6U^raBN_a9KQjmkus?6$JHZ*Mg5fo7;-|A)S0TYIfq`&)1wbRhzdK_^PKr z6KPE8H{^Wg?&s|}%fA^{b@bpFRhmyIAxvAz^)pH!?=8v1Sa0J%F^NS zYyaSmV`#CcUt5gviR@NxW15+_V+d9ZFnQE;rs&%cCc#zv(ut!VzTF%Obc0)rY{Bb8 z4jWX3=VRaxHsEV2uCwKuaVm!ybaZ?h{JnHrL(MJ-eVz7yIXB1pFeN@xN8F49jIDu4 zzx1i|^b*=}l7WP)d{3F<-poK%gK0Y7vUB`wdT?e2l1?B3KUw n>P>q z$oTPtZwEUipuI>A#M|Jh&|d>rCc9VZq^E`U%@D}L4eE2tJ6 Eh6W?^4CYb-9T)ramonnG>hm?0Y9&$4 zrFNZFPwIJik+X~+)+QZ{gv^7WqF#5dw)5B{1Ww0&pN+(t h^5k+aXg!)%ql z!x}`EIcX!P)uu&pR1+euvhXV^i^$3|^>hvgPJO62+h0bGJ)xtNXu;^1V=f?^R)0Ts z&e(EvO2TtBE7ZIu=#5LF0e=(5fj_sQb;LGlB{qw?)n==s&)pSl>l#hGJnl=pgL189 z;tLo8rz^MLfdKlhPj~V|#CBzW#28Qa`z^jlu;Q?l>%qDzE*ybmp${Lne!UgcdlC2y z*b4?S<~_TS_uh1Me;un4aZaV(6HoE=qQl4q6 @@HK6Ou)~&;5+L z0NpbzyJK9W@7b)jWFL#=*`co9+&}`)4+$nRV8EZY-T>U9n)uW;#1b`0q*4STRaS@T zjudr_Bt=z`PUwI4 l$)$-1kN6eQ^7dIw2Ea`?k^R#Cly z!9@UvMv~~5)aah@1EKHSLFgleNMH+~2?YW7fVo}mDgabz!4VSxefc}_Puw9kqCaPH z2BDD_39N1k6U5?zWnrDM)t$pGFb@?;7C8gpGj(DU+Fs{Z_o4}&v)^Ic5}ro)l;)1= zaQM%xI{evGng8SVkY8}HN#P%;yinLl_Ez;?z^!{Nk-TBE(GAFfbNwGRKUN>|i80Np zTRh~GAJbnJb8oN>OIm~ O^J~Rf8aI;paT_Xdqq$aUrBN zk~apc{=;J-6@=y`1J3;H7l1G6e@nFdUwYku0!LP({J34V(B$^BDziPVtH8P23pLWb zv1@>c8NG=_Rzl5y6XJ^^p$VPZO_W;~ijFOY<8%hWBfVy6CSD*4V-~Uq27n}!4?}Pw zm=aq^Iku(=b*l 7kX~Kvb-QYJqn)Q2^wp+s+S}-bMh=+EwE1 zzjOTESAVThg3UdHSzbc`VB*Y10yGBMiEr=$MjJ0^WPW4UP2fZhC|C%5;9vw0tVTWY z9mWFC5~%OE3Vst_3cWz7W0w#`ueRt~0BvH~qV*PR4q6;q{D&zh*S+wghO;Q`?b~PR zBv-?lqEMXCD_5DG2C<&IsyQk)@;bBrgFKJyXCZQW`nv$CKKnmu?xZv9YK`{qXFn^> z@%RHFIbAWsh{*RLF364d+Q&Gfg 1AMqc?vMnAB?#F&Hpc(nWa0&m#<+N2wJRr(DLoC+ok$#L;~!xT^xCN@N&i> zVImFRVO6r9!TT Mpz7*5LbFA!FqU3IH)3_Q=|UO{xoXUyTCw<% z&whog T)&f~PZbtED?(+&r{r|qKw?lM*MMWZOQ`=rpV<1WVR_KIlO>i6 zH%xSurCIZq1POdY^k{tesvv>fysv$>j8|7z&f+%t)7jZ!CgZ0ZezdNzhibQ!FluT@ zq5HTJj3`0#m0g?6hE9vrk;0BS0%u}l)|FOse%R*a;#sSzfag6ih3g5o6HObO_K2$L zH=NMDFY2P`xopLNNN|y>#lojzSPFAng~j{Y^q;!7N>-v468utAW 4Wn7*2-u1&F$67mFM=MLNb-di z&Z`i4%OYd_gX)^$G{h6mak7i!`Hx2|($bPM?;q>BVa;6ftiFyyhSl|Xt&JyAru$PL zmhj3FT4MnlbgM7&dP@aE`{0%K&`9GWZ0r;@ityxFWnKGaz@k6?9aioGCTxA-m8fb; z+U#_{2GN5;tr3{6Xx?v*Imf?xbDr3($WteUtGULQZuuSNZ3Zo{eTUV)p?|JlHkl}Z ztqx?fM60T})`w3k3ZyWfiLQh5hM?P$8#vUavN^bu85!g$hd@9pBWx}?HZIb1He)Qt z>2S@F2q)vpWCo6QhJ8t?J(I<55q%jQ+TpF}NO^s-Z*wRgk#X0$*#q(Y*IOrxm1;IT z(dW(f@S@7Am{FIq#20m*u3GyU3M=aKS2o_vh(GusJIRG jZW7(pDRB*Ed=cRvLivscx4!*&bY%=G zH#fh0#3$D~x@Dx#Eq#Xf!2K`YQ 5F=+rs=WgIcdsG*h3nzq9!Z-KU z0q$y(%##fjhNn6#M~kyt91hHmGsQjU?@2?e+SI4MV=J)hal5d%(XQHcGPm14uRUY@ zf^3_zfw5!(RUF#Ab7ueaNxs^OFmJ8UvBT3yz-?Dqx(IDix<(Mm^6vNcx@otkkLG6k zRG-nWK3~U3P7&8aaay={Ws7cE3_)M92db2-OLpBLuZ&;}>wdD*o7dAPDf=3k%a_ ki;H(env>!2T!xcru-nG&sJ=&xjPYyIF$~7bgo& z4C8=rFo)$VUZ|0n_fA}x&GbrXHny~Xs{irHm!tI`2rxn#(P5Ldbd{}i%**0H Y*&v&+YVf =^QLa z7ZNot`hU^!i7oR~>$por%(JTEhI5nIkhd_SKfYW Yg`+E(~3jRx~Pb3JyD z2}Jbi_23$ry_FcsrF4(h>ND?Sy9N)=)7-)coAJAer %~SFh8G-U?-9R zB|3m0R>rk3malO6CfkwzddOS4eR<4Xr1U_lgJw*%yyy|kBe#f!yr>%V>Lq4Jk&bR3 zoPJHWAx+1rb_YeLOIe$fOx^(?{uw2mbs4B3FNZ6vzcM9}!|fU_q$%LcDs}vdAD#(l zm&LFgH(tnC2^lr@^7&R{izFwD%FtZS7vmqj=wMk7U4rz+2~LZ9rf2vwTH|uAetd%v zPReF~o0&FD{oZ)5zv()YaarN>BwZP|0%mIRIBuA6A;W6o=!|J$gA3(Icr=ZAx}*;A zY9rY+n5D7Pwr^K|&C*PEjVeIOiNJFoL#$Dv!4z-MLmnmQXF1 >D! z=GJZ(hHsO5?-E;}-$LXYTqjt3X{ezdR>804PsN9Dx oIq<@~#G(W<1w&SfzvNUsc_HhR@+C$EBR4%Lcow
| zJe4B~oCgL_@M3@i2_1HkhNvL*^Y_gy_vi?ySOZ`igy&1gvqqaciQu#fx %D~` zI9Gr;)NZ_Hr+VAmXUk#jm=jmb_X~)PBy5@#Y}3V}{I;aL%oRdW 292D#(TqQpM zZrp7m+cSWb(g>Ze50MCIdooa^f?tuY?7b>ErvS~yulzftw>$S*E8-&tJ^#J~hWJ g1DQInFPo9E1V;lGGm z)YkfckRMBK4=@@NsZS)j=bwBqsNZBS|1i9M@g4u&1VBr>_rItYo)>E(f4$;((Vs6x zV&_%9+7x<=8{U(aHL0_Azwe6kbA9GxfJ1b+2$Gl}KqJ#C^af_?y84Zfj*Nc2 zrNU00Br>;NoK!V*7-!p7Rn6GtWyg5s$?3=^=B@cHVr-8!Rx+K4hlV_nE63Zu!xkK| z1OxZ$FV`~QQmsg7sFG>Hg6PSJBvN++`(@le-FU%23?tPo{e{ovzWYhj1H0)>I@q2) zLU`R2f|u{M=)n$C;Y7d=9w_)7Mh?bjP1lgmNu2($qIY4d1B#l@+aU2?=Mg!wmScA4 zN`D`oc602~c~iJPdW+tWfAezR^_X+*_j~ty= *`bDQxiPM!$jBXartpwqc$}B#-3(lk2w-g^Bv}wh#_}l1dw`JIAZQR0#}Uq=O<`= zoyYPWMn&}+YGGFg@-zfMl!cZ)@~zz>f}~S`Yc!yLljS>XzjZ~{#z8X(cL7Nh2qe>J zTxpocDY}d6n(H}~_(d?L>zq8l`SEGRi&w6DPnE@UaDT`ouevu3J^4J=vKmNnAf8F@ zZpWw-d;94LvL2&?{yNsf4kvI)K 4p+ z!}b9fV^NdxJ8YNJ;?-xUprpe<1x+R^43a*%&(J%zB-fAlQC~m$E5oz6r(>o)p4|uI z591iC{cFn(d7nueiKZtb#-4>1wYUgeh9K*kUypV+MsD$8Wz4|^$Y*w>O*qU)voz!| zqR+&dpFZ4D==r2LOLKxtQ^J>03x$O;%m`(a@fzj$KxWAcJl=`A-{-`7qbmk2jHJOe z*B#S~!_8kZ5I@WwL*BtooqT}f6g9Qo(DC)Gt5G#ldyCqclrhzed%~^Yp|>n>j-j>Z zN1d)~-Hc+^E?7K-V;|1)%7|?bU$T<9=5HZ?szWLJ#MrKo_2N4yi>6$fgSe0p>{GAL z(-OLDl>EIn kmIe ?Ux<;vz*1jA~BZ*$htM zIf-I;08xk4BPt*owgz+8@|#;jQizH1iPg-se=aVPD7xSoAnGTKBpj~+!&*B#L!F}a zPGQZQt;A3jbRa)u4JFQz{T?0qez55i3T}h y;fZ(rW+g$9GCb >iYqd6QDZ2&25E89{Who4~0p zXyz)7&65>88FWgf+}gPAWP!tP@%LV(@i5l&WSBj4#Ej`{EuORU 0Z z4X->WD83P@iw>|J=Ctc3ccOjPI||R`IFc2ZJMDe>WQek+cHQ1^IS%(-5zCo6bwq*O zMTf31&ajdeN + +[this-github]: https://github.com/accetto/ubuntu-vnc-xfce-g3/ +[this-changelog]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/CHANGELOG.md +[this-readme-full]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/xfce-firefox/README.md +[this-readme-project]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/README.md +[this-wiki]: https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki +[this-issues]: https://github.com/accetto/ubuntu-vnc-xfce-g3/issues + +[that-readme-startup-help]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/xfce/README-dockerhub.md#startup-options-and-help + + + +[this-docker]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-firefox-g3/ +[this-dockerfile]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/Dockerfile.xfce.firefox + +[this-screenshot-container]: https://raw.githubusercontent.com/accetto/ubuntu-vnc-xfce-g3/master/docker/xfce-firefox/ubuntu-vnc-xfce-firefox-plus.jpg + + + +[that-wiki-firefox-multiprocess]: https://github.com/accetto/xubuntu-vnc/wiki/Firefox-multiprocess + +[accetto-github-xubuntu-vnc]: https://github.com/accetto/xubuntu-vnc/ +[accetto-github-xubuntu-vnc-novnc]: https://github.com/accetto/xubuntu-vnc-novnc/ +[accetto-github-ubuntu-vnc-xfce-firefox]: https://github.com/accetto/ubuntu-vnc-xfce-firefox +[accetto-github-ubuntu-vnc-xfce-firefox-plus]: https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus + + + +[docker-ubuntu]: https://hub.docker.com/_/ubuntu/ + +[docker-doc]: https://docs.docker.com/ +[docker-doc-managing-data]: https://docs.docker.com/storage/ + +[jq]: https://stedolan.github.io/jq/ +[mousepad]: https://github.com/codebrainz/mousepad +[nano]: https://www.nano-editor.org/ +[novnc]: https://github.com/kanaka/noVNC +[tigervnc]: http://tigervnc.org +[tightvnc]: http://www.tightvnc.com +[tini]: https://github.com/krallin/tini +[xfce]: http://www.xfce.org + +[firefox]: https://www.mozilla.org +[firefox-doc-preferences]: https://developer.mozilla.org/en-US/docs/Mozilla/Preferences/A_brief_guide_to_Mozilla_preferences + + + +[badge-github-release]: https://badgen.net/github/release/accetto/ubuntu-vnc-xfce-g3?icon=github&label=release + +[badge-github-release-date]: https://img.shields.io/github/release-date/accetto/ubuntu-vnc-xfce-g3?logo=github + + + +[badge-docker-pulls]: https://badgen.net/docker/pulls/accetto/ubuntu-vnc-xfce-firefox-g3?icon=docker&label=pulls + +[badge-docker-stars]: https://badgen.net/docker/stars/accetto/ubuntu-vnc-xfce-firefox-g3?icon=docker&label=stars + + diff --git a/docker/xfce-firefox/README.md b/docker/xfce-firefox/README.md new file mode 100644 index 0000000..fa04360 --- /dev/null +++ b/docker/xfce-firefox/README.md @@ -0,0 +1,487 @@ +# Headless Ubuntu/Xfce container with VNC/noVNC and Firefox Browser + +## accetto/ubuntu-vnc-xfce-firefox-g3 + +[Docker Hub][this-docker] - [Git Hub][this-github] - [Dockerfile][this-dockerfile] - [Docker Readme][this-readme-dockerhub] - [Changelog][this-changelog] - [Project Readme][this-readme-project] - [Wiki][this-wiki] + +![badge-docker-pulls][badge-docker-pulls] +![badge-docker-stars][badge-docker-stars] +![badge-github-release][badge-github-release] +![badge-github-release-date][badge-github-release-date] + +- [Headless Ubuntu/Xfce container with VNC/noVNC and Firefox Browser](#headless-ubuntuxfce-container-with-vncnovnc-and-firefox-browser) + - [accetto/ubuntu-vnc-xfce-firefox-g3](#accettoubuntu-vnc-xfce-firefox-g3) + - [Image tags](#image-tags) + - [Ports](#ports) + - [Volumes](#volumes) + - [Version sticker](#version-sticker) + - [Using headless containers](#using-headless-containers) + - [Over VNC](#over-vnc) + - [Over noVNC](#over-novnc) + - [Container user accounts](#container-user-accounts) + - [Running containers in background (detached)](#running-containers-in-background-detached) + - [Running containers in foreground (interactively)](#running-containers-in-foreground-interactively) + - [Firefox multi-process](#firefox-multi-process) + - [Setting shared memory size](#setting-shared-memory-size) + - [Firefox preferences and the plus features](#firefox-preferences-and-the-plus-features) + - [Startup options and help](#startup-options-and-help) + - [Issues](#issues) + - [Credits](#credits) + +*** + +**Warning** about images with Firefox + +There is no single-process Firefox image in this repository and the multi-process mode is always enabled. Be aware, that multi-process requires larger shared memory (`/dev/shm`). At least 256MB is recommended. Please check the **Firefox multi-process** page in [this Wiki][that-wiki-firefox-multiprocess] for more information and the instructions, how to set the shared memory size in different scenarios. + +*** + +This repository contains resources for building Docker images based on [Ubuntu 20.04 LTS][docker-ubuntu] with [Xfce][xfce] desktop environment, [VNC][tigervnc]/[noVNC][novnc] servers for headless use and the current [Firefox Quantum][firefox] web browser. + +This is the **third generation** (G3) of my headless images. The **second generation** (G2) of similar images is contained in the GitHub repositories [accetto/xubuntu-vnc][accetto-github-xubuntu-vnc] and [accetto/xubuntu-vnc-novnc][accetto-github-xubuntu-vnc-novnc]. The **first generation** (G1) of similar images is contained in the GitHub repositories [accetto/ubuntu-vnc-xfce-firefox][accetto-github-ubuntu-vnc-xfce-firefox] and [accetto/ubuntu-vnc-xfce-firefox-plus][accetto-github-ubuntu-vnc-xfce-firefox-plus]. + +More information about the image generations can be found in the [project README][this-readme-project] file and in [Wiki][this-wiki]. + +The main features and components of the images in the default configuration are: + +utilities **ping**, **wget**, **sudo** (Ubuntu distribution) + +- current version of JSON processor [jq][jq] +- light-weight [Xfce][xfce] desktop environment (Ubuntu distribution) +- current version of high-performance [TigerVNC][tigervnc] server and client +- current version of [noVNC][novnc] HTML5 clients (full and lite) (TCP port **6901**) +- popular text editor [nano][nano] (Ubuntu distribution) +- lite but advanced graphical editor [mousepad][mousepad] (Ubuntu distribution) +- current version of [tini][tini] as the entry-point initial process (PID 1) +- support for overriding both the container user account and its group +- support of **version sticker** (see below) +- current version of [Firefox Quantum][firefox] web browser and some additional **plus** features described below + +The history of notable changes is documented in the [CHANGELOG][this-changelog]. + +![container-screenshot][this-screenshot-container] + +### Image tags + +The following image tags are regularly maintained and rebuilt: + +- `latest` is identical to `vnc-novnc-plus` +- `vnc` implements only VNC +- `vnc-novnc` implements VNC and noVNC +- `vnc-plus` implements only VNC and Firefox plus features +- `vnc-novnc-plus` implements VNC, noVNC and Firefox plus features + +Clicking on the version sticker badge in the [README on Docker Hub][this-readme-dockerhub] reveals more information about the actual configuration of the image. + +### Ports + +Following **TCP** ports are exposed: + +- **5901** used for access over **VNC** +- **6901** used for access over [noVNC][novnc] + +### Volumes + +The containers do not create or use any external volumes by default. However, the following folders make good mounting points: `/home/headless/Documents/`, `/home/headless/Downloads/`, `/home/headless/Pictures/`, `/home/headless/Public/` + +Both **named volumes** and **bind mounts** can be used. More about volumes can be found in the [Docker documentation][docker-doc] (e.g. [Manage data in Docker][docker-doc-managing-data]). + +### Version sticker + +Version sticker serves multiple purposes that are closer described in [Wiki][this-wiki]. Note that the usage of the version sticker has changed between the generations of images. + +The **short version sticker value** identifies the version of the docker image and it is persisted in its *label* when the image is built. It is also shown as a badge in the README file. + +The **verbose version sticker value** is used by the CI builder to decide if the image needs to be refreshed. It describes the actual configuration of essential components of the image. It can be revealed by clicking on the version sticker badge in the README file. + +The version sticker values are generated by the script `version_sticker.sh`, which is deployed into the startup directory `/dockerstartup`. The script will show a short help if executed with the argument `-h`. There is also a convenient `Version Sticker` launcher on the container desktop. + +## Using headless containers + +There are two ways, how to use the created headless containers. + +The default **VNC user** password is **headless** and it can be changed through the environment variable **VNC_PW**. For example the following container would use the password value **mynewpwd**: + +```shell +docker run -d -P -e VNC_PW=mynewpwd accetto/ubuntu-vnc-xfce-firefox-g3 +``` + +The argument `-P` means that the **VNC** and **noVNC** ports exposed by the container will be bound to the next free TCP ports on the host. It is also possible to bind them explicitly. For example: + +```shell +docker run -d -p 25901:5901 -p 26901:6901 accetto/ubuntu-vnc-xfce-firefox-g3 +``` + +In this case, if the host is named `mynas`, then **VNC** is accessible as `mynas:25091` and **noVNC** as `mynas:26901`. + +### Over VNC + +To be able to use the containers over **VNC**, some **VNC Viewer** is needed (e.g. [TigerVNC][tigervnc] or [TightVNC][tightvnc]). + +The VNC Viewer should connect to the host running the container, pointing to its TCP port mapped to the container's TCP port **5901**. + +For example, if the container has been created on the host called `mynas` using the parameters described above, the VNC Viewer should connect to `mynas:25901`. + +### Over noVNC + +To be able to use the containers over [noVNC][novnc], an HTML5 capable web browser is needed. It actually means, that any current web browser can be used. + +The browser should navigate to the host running the container, pointing to its TCP port mapped to the container's TCP port **6901**. + +The containers offer two [noVNC][novnc] clients - the **lite** client and the **full** client with more features. The connection URL differs slightly in both cases. To make it easier, a **simple startup page** is implemented. + +For example, if the container has been created on the host called `mynas` using the parameters described above, then the web browser should navigate to `http://mynas:26901`. + +The startup page will show two hyperlinks pointing to the both noVNC clients: + +- `http://mynas:26901/vnc_lite.html` +- `http://mynas:26901/vnc.html` + +It's also possible to provide the password through the links: + +- `http://mynas:26901/vnc_lite.html?password=headless` +- `http://mynas:26901/vnc.html?password=headless` + +## Container user accounts + +Containers created from this image run under the **default application user** (headless, 1001:0) with the default password set also to **headless**. This password can be changed inside the container using the following command: + +```shell +passwd +``` + +Please do not confuse the **default application user** password with the **VNC user** password, because they both have the same default value. However, the former one is used for **sudo** and it can be changed using `passwd` command. The latter one is used for VNC access and it can be changed through the **VNC_PW** environment variable (see above). + +The **sudo** command allows user elevation, so the **default application user** can, for example, install new applications. + +The following example shows how to install **git**: + +```shell +sudo apt-get update +sudo apt-get install -y git +``` + +Note that the default application account's **group membership** (group zero) does not give it automatically the privileges of the **root** user. Technical details will be described in [Wiki][this-wiki]. + +The container user ID (1001 by default) can be changed by creating the container using the `--user` parameter, for example: + +```shell +docker run -it -P --rm --user 2019 accetto/ubuntu-vnc-xfce-firefox-g3 +``` + +**Remark**: The following feature is available also for this image, but those specific image tags (`fugo`) are currently not built by default. However, you can enable the feature `FEATURES_USER_GROUP_OVERRIDE` in the hook scripts and build them yourself. + +The image supports also overriding the container user's group ID (0 by default). However, the image must be built with the argument `ARG_SUPPORT_USER_GROUP_OVERRIDE`. Otherwise the following command line would fail: + +```shell +### This will fail (Permission denied) +docker run -it -P --rm --user 2019:2000 accetto/ubuntu-vnc-xfce-g3:vnc-novnc + +### This will work (image built with ARG_SUPPORT_USER_GROUP_OVERRIDE) +docker run -it -P --rm --user 2019:2000 accetto/ubuntu-vnc-xfce-g3:vnc-novnc-fugo +``` + +The images having the tag suffix `-fugo` (**f**eatures **u**ser **g**roup **o**verride) are built just that way. + +Note that only numerical ID and GID are supported. Technical details will be described in [Wiki][this-wiki]. + +## Running containers in background (detached) + +The following container will keep running in the background and it will listen on an automatically selected TCP port on the host computer: + +```shell +docker run -dP accetto/ubuntu-vnc-xfce-firefox-g3 +``` + +The following container will listen on the host's TCP port **25901**: + +```shell +docker run -d -p 25901:5901 accetto/ubuntu-vnc-xfce-firefox-g3 +``` + +The following container will create (or re-use) the local named volume **my\_Downloads** mounted as `/home/headless/Downloads`: + +```shell +docker run -d -P -v my_Downloads:/home/headless/Downloads accetto/ubuntu-vnc-xfce-firefox-g3 +``` + +or using the newer syntax with **--mount** flag: + +```shell +docker run -d -P --mount source=my_Downloads,target=/home/headless/Downloads accetto/ubuntu-vnc-xfce-firefox-g3 +``` + +## Running containers in foreground (interactively) + +The following container can be used interactively: + +```shell +docker run -it --rm accetto/ubuntu-vnc-xfce-firefox-g3 bash +``` + +The opened `bash` session can be used as usual and then closed by entering `^C` (CTRL-C): + +```shell +To run a command as administrator (user "root"), use "sudo
". +See "man sudo_root" for details. + +headless@cf4a4e01d94b:~$ whoami +headless +headless@cf4a4e01d94b:~$ pwd +/home/headless +headless@cf4a4e01d94b:~$ +``` + +The container will remove itself. + +## Firefox multi-process + +Firefox multi-process (also known as **Electrolysis** or just **E10S**) can cause heavy crashing in Docker containers if there is not enough shared memory (**Gah. Your tab just crashed.**). + +In Firefox versions till **76.0.1** it has been possible to disable multi-process by setting the environment variable **MOZ_FORCE_DISABLE_E10S**. However, in Firefox **77.0.1** it has caused ugly scrambling of almost all web pages, because they were not decompressed. + +Mozilla has fixed the problem in the next release, but they warned about not supporting the switch in the future. That is why I've decided, that all images with Firefox will use multi-process by default, even if it requires larger shared memory. On the positive side, performance should be higher and Internet browsing should be sand-boxed. + +Please check the Wiki page [Firefox multi-process][that-wiki-firefox-multiprocess] for more information and the instructions, how the shared memory size can be set in different scenarios. + +### Setting shared memory size + +Instability of multi-process Firefox is caused by setting the shared memory size too low. Docker assigns only **64MB** by default. Testing on my computers has shown, that using at least **256MB** completely eliminates the problem. However, it could be different on your system. + +The Wiki page [Firefox multi-process][that-wiki-firefox-multiprocess] describes several ways, how to increase the shared memory size. It's really simple, if you need it for a single container started from the command line. + +For example, the following container will have its shared memory size set to 256MB: + +```shell +docker run -d -P --shm-size=256m accetto/ubuntu-vnc-xfce-firefox-g3 +``` + +You can check the current shared memory size by executing the following command inside the container: + +```shell +df -h /dev/shm +``` + +## Firefox preferences and the plus features + +Firefox browser supports pre-configuration of user preferences. + +Users can enforce their personal browser preferences if they put them into the `user.js` file and then copy it into the Firefox profile folder. The provided **plus** features make it really easy. + +There is the `/home/headless/firefox.plus` folder containing the `user.js` file and the helper utility `copy_firefox_user_preferences.sh`. It will copy the `user.js` file into one or more existing Firefox profiles. The utility is easy to use, because it is interactive and it will also display the help, if started with the `-h` or `--help` argument. + +To make it even more convenient, there are also desktop launchers for the utility and for the **Firefox Profile Manager**. + +Recommended procedure for taking advantage of the **plus** features is: + +- Start the **Firefox Profile Manager** using the desktop launcher **FF Profile Manager**. Create a new Firefox profile if there is none or you want to add one more. Wait until the profile is created and then start Firefox with it. Starting Firefox is required to create the actual profile content. + + **Hint**: You can also check the **Work offline** check-box before creating the profile. + + The Firefox profiles are created inside the `/home/headless/.mozilla/firefox` folder by default. Note that the `.mozilla` folder is hidden. + + Close the **Profile Manager** by pushing the **Exit** button. + +- Put your personal Firefox preferences into the `user.js` file which is in the `/home/headless/firefox.plus`folder. Check the Firefox documentation (e.g. [Firefox preferences][firefox-doc-preferences]) for more information about the syntax. + + **Hint**: There is also another way. You can first start Firefox, configure it and then copy the content of the `prefs.js` file from the Firefox profile folder into the `user.js` file. Then you can check the content and to keep only the preferences you really want to enforce. It's not a quick task, but you have to do it only once or until you need an update. + +- Start the helper utility using the desktop launcher **Copy FF Preferences**. The utility will allow you to copy the `user.js` file to any of the existing Firefox profiles. + + **Hint**: You preferences will be enforced until you delete the `user.js` file from the Firefox profile folder. + +It is also very easy to build customized images with pre-filled `user.js` files. + +## Startup options and help + +The image supports multiple **start-up options** and **start-up modifiers**. There also also two help modes. + +The following container will print out the short help and then it will remove itself: + +```shell +docker run --rm accetto/ubuntu-vnc-xfce-firefox-g3 --help +``` + +Example of the short help text: + +```text +Container startup script +Usage: /dockerstartup/startup.sh [-v|--version] [-h|--help] [-H|--help-usage] [--(no-)wait] [--(no-)skip-startup] [--(no-)tail-null] [--(no-)tail-vnc] [--(no-)version-sticker] [--(no-)version-sticker-verbose] [--(no-)skip-vnc] [--(no-)skip-novnc] [--(no-)debug] [--(no-)verbose] [--] [ ] ... [ ] ... + : Optional command with optional arguments. It is executed during startup. + -v, --version: Prints version + -h, --help: Prints help + -H, --help-usage: Extended container usage help. + --wait, --no-wait: Default background execution mode (on by default) + --skip-startup, --no-skip-startup: Default foreground execution mode (off by default) + --tail-null, --no-tail-null: Alternative background execution mode (off by default) + --tail-vnc, --no-tail-vnc: Alternative background execution mode (off by default) + --version-sticker, --no-version-sticker: Alternative foreground execution mode (off by default) + --version-sticker-verbose, --no-version-sticker-verbose: Alternative foreground execution mode (off by default) + --skip-vnc, --no-skip-vnc: Startup process modifier (off by default) + --skip-novnc, --no-skip-novnc: Startup process modifier (off by default) + --debug, --no-debug: Startup process modifier (off by default) + --verbose, --no-verbose: Startup process modifier (off by default) + +Use '-H' or '--help-usage' for extended container usage help. +For more information visit https://github.com/accetto/ubuntu-vnc-xfce-g3 +``` + +The following container will print out the long help and then it will remove itself: + +```shell +docker run --rm accetto/ubuntu-vnc-xfce-chromium-g3 --help-usage +``` + +Example of the long help text: + +```text +CONTAINER USAGE: +docker run [ ] accetto/ : [ ] [ ] + +POSITIONAL ARGUMENTS: +command + Optional command with optional arguments. + It will be executed during startup before going waiting, tailing or asleep. + It is necessary to use the quotes correctly or the 'bash -c " "' pattern. + +STARTUP OPTIONS: + +--wait, or no options, or unknown option, or empty input + Default background execution mode. + Starts the VNC and noVNC servers, if available, then executes the command + and waits until the VNC server process exits or goes asleep infinitely. + Container keeps running in the background. + +--skip-startup + Default foreground execution mode. + Skips the startup procedure, executes the command and exits. + Be aware that the container user generator will be also skipped. + Container does not keep running in the background. + +--tail-null + Alternative background execution mode. + Similar to '--wait', but tails the null device instead of going asleep. + Container keeps running in the background. + +--tail-vnc + Alternative background execution mode. + Similar to '--wait', but tails the VNC log instead of waiting until the VNC process exits. + Falls back to '--tail-null' if the VNC server has not been started. + Container keeps running in the background. + +--version-sticker + Alternative foreground execution mode. + Prints out the version sticker info. + The VNC server is also started by default, if available, because some applications + need a display to report their versions correctly. It can be suppressed by providing + also '--skip-vnc'. The '--skip-novnc' option is always enforced automatically. + Container does not keep running in the background. + +--version-sticker-verbose + Alternative foreground execution mode. + Similar to '--version-sticker', but prints out the verbose version sticker info and features list. + Container does not keep running in the background. + +--skip-vnc + Startup process modifier. + If VNC and noVNC startup should be skipped. + It also enforces '--skip-novnc'. + +--skip-novnc + Startup process modifier. + If noVNC startup should be skipped. + It is also enforced by '--skip-vnc'. + +--debug + Startup process modifier. + If additional debugging info should be displayed during startup. + It also enforces option '--verbose'. + +--verbose + Startup process modifier. + If startup progress messages should be displayed. + It is also enforced by '--debug'. + +--help-usage, -H + Prints out this extended container usage help and exits. + The rest of the input is ignored. + +--help, -h + Prints out the short startup script help and exits. + The rest of the input is ignored. + +--version, -v + Prints out the version of the startup script and exits. + The rest of the input is ignored. + +Use '-h' or '--help' for short startup script help. +Fore more information visit https://github.com/accetto/ubuntu-vnc-xfce-g3 +``` + +## Issues + +If you have found a problem or you just have a question, please check the [Issues][this-issues] and the [Wiki][this-wiki] first. Please do not overlook the closed issues. + +If you do not find a solution, you can file a new issue. The better you describe the problem, the bigger the chance it'll be solved soon. + +## Credits + +Credit goes to all the countless people and companies, who contribute to open source community and make so many dreamy things real. + +*** + + + +[this-github]: https://github.com/accetto/ubuntu-vnc-xfce-g3/ +[this-changelog]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/CHANGELOG.md +[this-readme-dockerhub]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-firefox-g3 +[this-readme-project]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/README.md +[this-wiki]: https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki +[this-issues]: https://github.com/accetto/ubuntu-vnc-xfce-g3/issues + + + +[this-docker]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-firefox-g3/ +[this-dockerfile]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/Dockerfile.xfce.firefox + +[this-screenshot-container]: https://raw.githubusercontent.com/accetto/ubuntu-vnc-xfce-g3/master/docker/xfce-firefox/ubuntu-vnc-xfce-firefox-plus.jpg + + + +[that-wiki-firefox-multiprocess]: https://github.com/accetto/xubuntu-vnc/wiki/Firefox-multiprocess + +[accetto-github-xubuntu-vnc]: https://github.com/accetto/xubuntu-vnc/ +[accetto-github-xubuntu-vnc-novnc]: https://github.com/accetto/xubuntu-vnc-novnc/ +[accetto-github-ubuntu-vnc-xfce-firefox]: https://github.com/accetto/ubuntu-vnc-xfce-firefox +[accetto-github-ubuntu-vnc-xfce-firefox-plus]: https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus + + + +[docker-ubuntu]: https://hub.docker.com/_/ubuntu/ + +[docker-doc]: https://docs.docker.com/ +[docker-doc-managing-data]: https://docs.docker.com/storage/ + +[jq]: https://stedolan.github.io/jq/ +[mousepad]: https://github.com/codebrainz/mousepad +[nano]: https://www.nano-editor.org/ +[novnc]: https://github.com/kanaka/noVNC +[tigervnc]: http://tigervnc.org +[tightvnc]: http://www.tightvnc.com +[tini]: https://github.com/krallin/tini +[xfce]: http://www.xfce.org + +[firefox]: https://www.mozilla.org +[firefox-doc-preferences]: https://developer.mozilla.org/en-US/docs/Mozilla/Preferences/A_brief_guide_to_Mozilla_preferences + + + +[badge-github-release]: https://badgen.net/github/release/accetto/ubuntu-vnc-xfce-g3?icon=github&label=release + +[badge-github-release-date]: https://img.shields.io/github/release-date/accetto/ubuntu-vnc-xfce-g3?logo=github + + + +[badge-docker-pulls]: https://badgen.net/docker/pulls/accetto/ubuntu-vnc-xfce-firefox-g3?icon=docker&label=pulls + +[badge-docker-stars]: https://badgen.net/docker/stars/accetto/ubuntu-vnc-xfce-firefox-g3?icon=docker&label=stars diff --git a/docker/xfce-firefox/readme-append.template b/docker/xfce-firefox/readme-append.template new file mode 100644 index 0000000..68f02ca --- /dev/null +++ b/docker/xfce-firefox/readme-append.template @@ -0,0 +1,42 @@ + + + + + +[badge_latest_created]: https://badgen.net/https/gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@latest@created.json + +[badge_latest_version-sticker]: https://badgen.net/https/gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@latest@version-sticker.json + +[link_latest_version-sticker-verbose]: https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@latest@version-sticker-verbose.txt + + + +[badge_vnc_created]: https://badgen.net/https/gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@vnc@created.json + +[badge_vnc_version-sticker]: https://badgen.net/https/gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@vnc@version-sticker.json + +[link_vnc_version-sticker-verbose]: https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@vnc@version-sticker-verbose.txt + + + +[badge_vnc-novnc_created]: https://badgen.net/https/gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@vnc-novnc@created.json + +[badge_vnc-novnc_version-sticker]: https://badgen.net/https/gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@vnc-novnc@version-sticker.json + +[link_vnc-novnc_version-sticker-verbose]: https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@vnc-novnc@version-sticker-verbose.txt + + + +[badge_vnc-plus_created]: https://badgen.net/https/gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@vnc-plus@created.json + +[badge_vnc-plus_version-sticker]: https://badgen.net/https/gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@vnc-plus@version-sticker.json + +[link_vnc-plus_version-sticker-verbose]: https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@vnc-plus@version-sticker-verbose.txt + + + +[badge_vnc-novnc-plus_created]: https://badgen.net/https/gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@vnc-novnc-plus@created.json + +[badge_vnc-novnc-plus_version-sticker]: https://badgen.net/https/gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@vnc-novnc-plus@version-sticker.json + +[link_vnc-novnc-plus_version-sticker-verbose]: https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@vnc-novnc-plus@version-sticker-verbose.txt diff --git a/docker/xfce-firefox/src/firefox.plus/home/Desktop/Copy FF Preferences.desktop b/docker/xfce-firefox/src/firefox.plus/home/Desktop/Copy FF Preferences.desktop new file mode 100644 index 0000000..fefa40e --- /dev/null +++ b/docker/xfce-firefox/src/firefox.plus/home/Desktop/Copy FF Preferences.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=Copy FF Preferences +Comment=Copy user.js into Firefox profiles +Exec=/home/headless/firefox.plus/copy_firefox_user_preferences.sh +Icon=accetto +Path= +Terminal=true +StartupNotify=true +GenericName=Copy FF Preferences diff --git a/docker/xfce-firefox/src/firefox.plus/home/Desktop/FF Profile Manager.desktop b/docker/xfce-firefox/src/firefox.plus/home/Desktop/FF Profile Manager.desktop new file mode 100644 index 0000000..b96e7e0 --- /dev/null +++ b/docker/xfce-firefox/src/firefox.plus/home/Desktop/FF Profile Manager.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=FF Profile Manager +Comment=Open Firefox Profile Manager +Exec=firefox -P +Icon=accetto +Path= +Terminal=false +StartupNotify=true diff --git a/docker/xfce-firefox/src/firefox.plus/resources/accetto.svg b/docker/xfce-firefox/src/firefox.plus/resources/accetto.svg new file mode 100644 index 0000000..cbb3d9f --- /dev/null +++ b/docker/xfce-firefox/src/firefox.plus/resources/accetto.svg @@ -0,0 +1,116 @@ + + + + diff --git a/docker/xfce-firefox/src/firefox.plus/resources/copy_firefox_user_preferences.sh b/docker/xfce-firefox/src/firefox.plus/resources/copy_firefox_user_preferences.sh new file mode 100644 index 0000000..ab0492c --- /dev/null +++ b/docker/xfce-firefox/src/firefox.plus/resources/copy_firefox_user_preferences.sh @@ -0,0 +1,196 @@ +#!/bin/bash +### @accetto (https://github.com/accetto) (https://hub.docker.com/u/accetto/) + +# ARG_OPTIONAL_SINGLE([source],[s],[Source folder (where 'user.js' is).],[${HOME}/firefox.plus]) +# ARG_OPTIONAL_SINGLE([target],[t],[Target folder (where Firefox profiles are).],[${HOME}/.mozilla/firefox]) +# ARG_VERSION([echo $0 v19.06.18]) +# ARG_HELP([Copy 'user.js' into existing Firefox profiles]) +# ARGBASH_GO() +# needed because of Argbash --> m4_ignore([ +### START OF CODE GENERATED BY Argbash v2.8.0 one line above ### +# Argbash is a bash code generator used to get arguments parsing right. +# Argbash is FREE SOFTWARE, see https://argbash.io for more info + + +die() +{ + local _ret=$2 + test -n "$_ret" || _ret=1 + test "$_PRINT_HELP" = yes && print_help >&2 + echo "$1" >&2 + exit ${_ret} +} + + +begins_with_short_option() +{ + local first_option all_short_options='stvh' + first_option="${1:0:1}" + test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0 +} + +# THE DEFAULTS INITIALIZATION - OPTIONALS +_arg_source="${HOME}/firefox.plus" +_arg_target="${HOME}/.mozilla/firefox" + + +print_help() +{ + printf '%s\n' "Copy 'user.js' into existing Firefox profiles" + printf 'Usage: %s [-s|--source ] [-t|--target ] [-v|--version] [-h|--help]\n' "$0" + printf '\t%s\n' "-s, --source: Source folder (where 'user.js' is). (default: '${HOME}/firefox.plus')" + printf '\t%s\n' "-t, --target: Target folder (where Firefox profiles are). (default: '${HOME}/.mozilla/firefox')" + printf '\t%s\n' "-v, --version: Prints version" + printf '\t%s\n' "-h, --help: Prints help" +} + + +parse_commandline() +{ + while test $# -gt 0 + do + _key="$1" + case "$_key" in + -s|--source) + test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 + _arg_source="$2" + shift + ;; + --source=*) + _arg_source="${_key##--source=}" + ;; + -s*) + _arg_source="${_key##-s}" + ;; + -t|--target) + test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 + _arg_target="$2" + shift + ;; + --target=*) + _arg_target="${_key##--target=}" + ;; + -t*) + _arg_target="${_key##-t}" + ;; + -v|--version) + echo $0 v19.06.18 + exit 0 + ;; + -v*) + echo $0 v19.06.18 + exit 0 + ;; + -h|--help) + print_help + exit 0 + ;; + -h*) + print_help + exit 0 + ;; + *) + _PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1 + ;; + esac + shift + done +} + +parse_commandline "$@" + +# OTHER STUFF GENERATED BY Argbash + +### END OF CODE GENERATED BY Argbash (sortof) ### ]) +# [ <-- needed because of Argbash + +_counter=0 +_file_userjs="user.js" +_file_profilesini="profiles.ini" +_full_userjs="" +_full_profilesini="" +_input="" +_line=0 +_mark="" +_oldIFS="" +declare -a _list + +# LOCAL_DEBUG=true + +[[ $LOCAL_DEBUG ]] && _arg_source="." +[[ $LOCAL_DEBUG ]] && _arg_target="../.mozilla/firefox" + +fn_die() +{ + local _ret=$2 + test -n "$_ret" || _ret=1 + test "$_PRINT_HELP" = yes && print_help >&2 + echo "$1" >&2 + read -rp $"Press any key to close this window ... " -n1 _input + exit ${_ret} +} + +### source and target folders must be provided +# : ${_arg_source?} ${_arg_target?} +[[ ! ${_arg_source} ]] && fn_die "Source path must be provided!" +[[ ! ${_arg_target} ]] && fn_die "Target path must be provided!" + +_full_userjs="${_arg_source}/${_file_userjs}" +_full_profilesini="${_arg_target}/${_file_profilesini}" + +### source folder must contain 'user.js' +[[ -f "${_full_userjs}" ]] && echo "File '${_full_userjs}' found." || fn_die "File '${_full_userjs}' not found!" + +### target folder must contain 'profiles.ini' +[[ -f ${_full_profilesini} ]] && echo "File '${_full_profilesini}' found." || fn_die "File '${_full_profilesini}' not found!" + +### only profiles in 'profiles.ini' will be processed, get their count +_counter=$( grep -c -E '^Path=' "${_full_profilesini}" ) + +if [[ $_counter -gt 0 ]] ; then + + ### extract profile folder names from 'profiles.ini' into the array + ### be aware that user profile names/folders can contain spaces + _oldIFS=$IFS + IFS=$'\x0A'$'\x0D' + _list=( $( grep -E '^Path=' "${_full_profilesini}" | sed -E -e 's/^Path=//' ) ) + IFS=$_oldIFS + + echo "Following profiles found in '${_file_profilesini}' ('+|-' means with/without '${_file_userjs}'):" + _counter=0 + for p in "${_list[@]}" ; do + _counter=$((${_counter}+1)) + [[ $(ls "${_arg_target}/$p/${_file_userjs}" 2>/dev/null) ]] && _mark=" + " || _mark=" - " + printf ' %s %s %s\n' "$_counter" "$_mark" "$p" + done + + ### user interaction + read -rp $"Into which profile to copy '${_file_userjs}' (line number or 'all')? " _input + _input=$(echo ${_input,,} | grep -i -E "^[0-9]+$|^all$") + [[ ! ${_input} ]] && fn_die "INTERRUPTED: Line number or 'all' required!" + if [[ "${_input,,}" != "all" ]] ; then + + ### line number has been provided + _line=${_input} + [[ ${_line} -lt 1 || ${_line} -gt ${_counter} ]] && fn_die "Line number must be from the interval [1..${_counter}]!" + _line=$((${_line}-1)) + + ### copy 'user.js' into the selected profile folder + cp -v "${_full_userjs}" "${_arg_target}/${_list[${_line}]}/" + + else + # 'all' has been provided + ### copy 'user.js' into all profiles not containing it yet + for p in "${_list[@]}" ; do + cp -v "${_full_userjs}" "${_arg_target}/$p/" + done + fi + + fn_die "SUCCESS." 0 +else + echo "No profiles found in '${_full_profilesini}'." +fi + +fn_die "" 0 + +# ] <-- needed because of Argbash diff --git a/docker/xfce-firefox/src/firefox.plus/resources/user.js b/docker/xfce-firefox/src/firefox.plus/resources/user.js new file mode 100644 index 0000000..a06b4fa --- /dev/null +++ b/docker/xfce-firefox/src/firefox.plus/resources/user.js @@ -0,0 +1,6 @@ +// Add the preferences you want to force here. +// They will be forced for each session, but only in profiles containing this file. + +// Disable WebRTC leaks as explained in https://ipleak.net/#webrtcleak +// Be aware that this has impact on some applications, e.g. some messengers. +// user_pref("media.peerconnection.enabled", false); diff --git a/docker/xfce-firefox/src/home/Desktop/firefox.desktop b/docker/xfce-firefox/src/home/Desktop/firefox.desktop new file mode 100644 index 0000000..0c2d32d --- /dev/null +++ b/docker/xfce-firefox/src/home/Desktop/firefox.desktop @@ -0,0 +1,222 @@ +[Desktop Entry] +Version=1.0 +Name=Firefox Web Browser +Name[ar]=متصفح الويب فَيَرفُكْس +Name[ast]=Restolador web Firefox +Name[bn]=ফায়ারফক্স ওয়েব ব্রাউজার +Name[ca]=Navegador web Firefox +Name[cs]=Firefox Webový prohlížeč +Name[da]=Firefox - internetbrowser +Name[el]=Περιηγητής Firefox +Name[es]=Navegador web Firefox +Name[et]=Firefoxi veebibrauser +Name[fa]=مرورگر اینترنتی Firefox +Name[fi]=Firefox-selain +Name[fr]=Navigateur Web Firefox +Name[gl]=Navegador web Firefox +Name[he]=דפדפן האינטרנט Firefox +Name[hr]=Firefox web preglednik +Name[hu]=Firefox webböngésző +Name[it]=Firefox Browser Web +Name[ja]=Firefox ウェブ・ブラウザ +Name[ko]=Firefox 웹 브라우저 +Name[ku]=Geroka torê Firefox +Name[lt]=Firefox interneto naršyklė +Name[nb]=Firefox Nettleser +Name[nl]=Firefox webbrowser +Name[nn]=Firefox Nettlesar +Name[no]=Firefox Nettleser +Name[pl]=Przeglądarka WWW Firefox +Name[pt]=Firefox Navegador Web +Name[pt_BR]=Navegador Web Firefox +Name[ro]=Firefox – Navigator Internet +Name[ru]=Веб-браузер Firefox +Name[sk]=Firefox - internetový prehliadač +Name[sl]=Firefox spletni brskalnik +Name[sv]=Firefox webbläsare +Name[tr]=Firefox Web Tarayıcısı +Name[ug]=Firefox توركۆرگۈ +Name[uk]=Веб-браузер Firefox +Name[vi]=Trình duyệt web Firefox +Name[zh_CN]=Firefox 网络浏览器 +Name[zh_TW]=Firefox 網路瀏覽器 +Comment=Browse the World Wide Web +Comment[ar]=تصفح الشبكة العنكبوتية العالمية +Comment[ast]=Restola pela Rede +Comment[bn]=ইন্টারনেট ব্রাউজ করুন +Comment[ca]=Navegueu per la web +Comment[cs]=Prohlížení stránek World Wide Webu +Comment[da]=Surf på internettet +Comment[de]=Im Internet surfen +Comment[el]=Μπορείτε να περιηγηθείτε στο διαδίκτυο (Web) +Comment[es]=Navegue por la web +Comment[et]=Lehitse veebi +Comment[fa]=صفحات شبکه جهانی اینترنت را مرور نمایید +Comment[fi]=Selaa Internetin WWW-sivuja +Comment[fr]=Naviguer sur le Web +Comment[gl]=Navegar pola rede +Comment[he]=גלישה ברחבי האינטרנט +Comment[hr]=Pretražite web +Comment[hu]=A világháló böngészése +Comment[it]=Esplora il web +Comment[ja]=ウェブを閲覧します +Comment[ko]=웹을 돌아 다닙니다 +Comment[ku]=Li torê bigere +Comment[lt]=Naršykite internete +Comment[nb]=Surf på nettet +Comment[nl]=Verken het internet +Comment[nn]=Surf på nettet +Comment[no]=Surf på nettet +Comment[pl]=Przeglądanie stron WWW +Comment[pt]=Navegue na Internet +Comment[pt_BR]=Navegue na Internet +Comment[ro]=Navigați pe Internet +Comment[ru]=Доступ в Интернет +Comment[sk]=Prehliadanie internetu +Comment[sl]=Brskajte po spletu +Comment[sv]=Surfa på webben +Comment[tr]=İnternet'te Gezinin +Comment[ug]=دۇنيادىكى توربەتلەرنى كۆرگىلى بولىدۇ +Comment[uk]=Перегляд сторінок Інтернету +Comment[vi]=Để duyệt các trang web +Comment[zh_CN]=浏览互联网 +Comment[zh_TW]=瀏覽網際網路 +GenericName=Web Browser +GenericName[ar]=متصفح ويب +GenericName[ast]=Restolador Web +GenericName[bn]=ওয়েব ব্রাউজার +GenericName[ca]=Navegador web +GenericName[cs]=Webový prohlížeč +GenericName[da]=Webbrowser +GenericName[el]=Περιηγητής διαδικτύου +GenericName[es]=Navegador web +GenericName[et]=Veebibrauser +GenericName[fa]=مرورگر اینترنتی +GenericName[fi]=WWW-selain +GenericName[fr]=Navigateur Web +GenericName[gl]=Navegador Web +GenericName[he]=דפדפן אינטרנט +GenericName[hr]=Web preglednik +GenericName[hu]=Webböngésző +GenericName[it]=Browser web +GenericName[ja]=ウェブ・ブラウザ +GenericName[ko]=웹 브라우저 +GenericName[ku]=Geroka torê +GenericName[lt]=Interneto naršyklė +GenericName[nb]=Nettleser +GenericName[nl]=Webbrowser +GenericName[nn]=Nettlesar +GenericName[no]=Nettleser +GenericName[pl]=Przeglądarka WWW +GenericName[pt]=Navegador Web +GenericName[pt_BR]=Navegador Web +GenericName[ro]=Navigator Internet +GenericName[ru]=Веб-браузер +GenericName[sk]=Internetový prehliadač +GenericName[sl]=Spletni brskalnik +GenericName[sv]=Webbläsare +GenericName[tr]=Web Tarayıcı +GenericName[ug]=توركۆرگۈ +GenericName[uk]=Веб-браузер +GenericName[vi]=Trình duyệt Web +GenericName[zh_CN]=网络浏览器 +GenericName[zh_TW]=網路瀏覽器 +Keywords=Internet;WWW;Browser;Web;Explorer +Keywords[ar]=انترنت;إنترنت;متصفح;ويب;وب +Keywords[ast]=Internet;WWW;Restolador;Web;Esplorador +Keywords[ca]=Internet;WWW;Navegador;Web;Explorador;Explorer +Keywords[cs]=Internet;WWW;Prohlížeč;Web;Explorer +Keywords[da]=Internet;Internettet;WWW;Browser;Browse;Web;Surf;Nettet +Keywords[de]=Internet;WWW;Browser;Web;Explorer;Webseite;Site;surfen;online;browsen +Keywords[el]=Internet;WWW;Browser;Web;Explorer;Διαδίκτυο;Περιηγητής;Firefox;Φιρεφοχ;Ιντερνετ +Keywords[es]=Explorador;Internet;WWW +Keywords[fi]=Internet;WWW;Browser;Web;Explorer;selain;Internet-selain;internetselain;verkkoselain;netti;surffaa +Keywords[fr]=Internet;WWW;Browser;Web;Explorer;Fureteur;Surfer;Navigateur +Keywords[he]=דפדפן;אינטרנט;רשת;אתרים;אתר;פיירפוקס;מוזילה; +Keywords[hr]=Internet;WWW;preglednik;Web +Keywords[hu]=Internet;WWW;Böngésző;Web;Háló;Net;Explorer +Keywords[it]=Internet;WWW;Browser;Web;Navigatore +Keywords[is]=Internet;WWW;Vafri;Vefur;Netvafri;Flakk +Keywords[ja]=Internet;WWW;Web;インターネット;ブラウザ;ウェブ;エクスプローラ +Keywords[nb]=Internett;WWW;Nettleser;Explorer;Web;Browser;Nettside +Keywords[nl]=Internet;WWW;Browser;Web;Explorer;Verkenner;Website;Surfen;Online +Keywords[pt]=Internet;WWW;Browser;Web;Explorador;Navegador +Keywords[pt_BR]=Internet;WWW;Browser;Web;Explorador;Navegador +Keywords[ru]=Internet;WWW;Browser;Web;Explorer;интернет;браузер;веб;файрфокс;огнелис +Keywords[sk]=Internet;WWW;Prehliadač;Web;Explorer +Keywords[sl]=Internet;WWW;Browser;Web;Explorer;Brskalnik;Splet +Keywords[tr]=İnternet;WWW;Tarayıcı;Web;Gezgin;Web sitesi;Site;sörf;çevrimiçi;tara +Keywords[uk]=Internet;WWW;Browser;Web;Explorer;Інтернет;мережа;переглядач;оглядач;браузер;веб;файрфокс;вогнелис;перегляд +Keywords[vi]=Internet;WWW;Browser;Web;Explorer;Trình duyệt;Trang web +Keywords[zh_CN]=Internet;WWW;Browser;Web;Explorer;网页;浏览;上网;火狐;Firefox;ff;互联网;网站; +Keywords[zh_TW]=Internet;WWW;Browser;Web;Explorer;網際網路;網路;瀏覽器;上網;網頁;火狐 +Exec=firefox %u +Terminal=false +X-MultipleArgs=false +Type=Application +Icon=firefox +Categories=GNOME;GTK;Network;WebBrowser; +MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;x-scheme-handler/chrome;video/webm;application/x-xpinstall; +StartupNotify=true +Actions=new-window;new-private-window; + +[Desktop Action new-window] +Name=Open a New Window +Name[ar]=افتح نافذة جديدة +Name[ast]=Abrir una ventana nueva +Name[bn]=Abrir una ventana nueva +Name[ca]=Obre una finestra nova +Name[cs]=Otevřít nové okno +Name[da]=Åbn et nyt vindue +Name[de]=Ein neues Fenster öffnen +Name[el]=Νέο παράθυρο +Name[es]=Abrir una ventana nueva +Name[fi]=Avaa uusi ikkuna +Name[fr]=Ouvrir une nouvelle fenêtre +Name[gl]=Abrir unha nova xanela +Name[he]=פתיחת חלון חדש +Name[hr]=Otvori novi prozor +Name[hu]=Új ablak nyitása +Name[it]=Apri una nuova finestra +Name[ja]=新しいウィンドウを開く +Name[ko]=새 창 열기 +Name[ku]=Paceyeke nû veke +Name[lt]=Atverti naują langą +Name[nb]=Åpne et nytt vindu +Name[nl]=Nieuw venster openen +Name[pt]=Abrir nova janela +Name[pt_BR]=Abrir nova janela +Name[ro]=Deschide o fereastră nouă +Name[ru]=Новое окно +Name[sk]=Otvoriť nové okno +Name[sl]=Odpri novo okno +Name[sv]=Öppna ett nytt fönster +Name[tr]=Yeni pencere aç +Name[ug]=يېڭى كۆزنەك ئېچىش +Name[uk]=Відкрити нове вікно +Name[vi]=Mở cửa sổ mới +Name[zh_CN]=新建窗口 +Name[zh_TW]=開啟新視窗 +Exec=firefox -new-window + +[Desktop Action new-private-window] +Name=Open a New Private Window +Name[ar]=افتح نافذة جديدة للتصفح الخاص +Name[ca]=Obre una finestra nova en mode d'incògnit +Name[cs]=Otevřít nové anonymní okno +Name[de]=Ein neues privates Fenster öffnen +Name[el]=Νέο ιδιωτικό παράθυρο +Name[es]=Abrir una ventana privada nueva +Name[fi]=Avaa uusi yksityinen ikkuna +Name[fr]=Ouvrir une nouvelle fenêtre de navigation privée +Name[he]=פתיחת חלון גלישה פרטית חדש +Name[hu]=Új privát ablak nyitása +Name[it]=Apri una nuova finestra anonima +Name[nb]=Åpne et nytt privat vindu +Name[ru]=Новое приватное окно +Name[sl]=Odpri novo okno zasebnega brskanja +Name[sv]=Öppna ett nytt privat fönster +Name[tr]=Yeni gizli pencere aç +Name[uk]=Відкрити нове вікно у потайливому режимі +Name[zh_TW]=開啟新隱私瀏覽視窗 +Exec=firefox -private-window diff --git a/docker/xfce-firefox/src/startup/version_sticker.sh b/docker/xfce-firefox/src/startup/version_sticker.sh new file mode 100644 index 0000000..8be860e --- /dev/null +++ b/docker/xfce-firefox/src/startup/version_sticker.sh @@ -0,0 +1,62 @@ +#!/bin/bash +### @accetto, September 2019 + +### resolve also symlinks +_current_dir="$(dirname "$(readlink -f "$0")")" + +ubuntu=$("${_current_dir}/version_of.sh" ubuntu) +firefox=$("${STARTUPDIR}/version_of.sh" firefox) + +main() { + local key + + if [ $# -gt 0 ] ; then + while [ $# -gt 0 ] ; do + key="$1" + if [ "${key}" = '--' ] ; then shift ; fi + case "${key}" in + -h ) + echo "Usage: version_sticker [-h] [-v] [-V] [-f]" + echo "-h help" + echo "-v short version sticker" + echo "-V verbose version sticker" + echo "-f features" + ;; + -v ) + echo "Ubuntu ${ubuntu}" + echo "Firefox ${firefox}" + ;; + -V ) + echo "Ubuntu ${ubuntu}" + version=$("${_current_dir}/version_of.sh" nano) + if [ -n "${version}" ] ; then echo "nano ${version}" ; fi + version=$("${_current_dir}/version_of.sh" jq) + if [ -n "${version}" ] ; then echo "jq ${version}" ; fi + version=$("${_current_dir}/version_of.sh" mousepad) + if [ -n "${version}" ] ; then echo "Mousepad ${version}" ; fi + version=$("${_current_dir}/version_of.sh" tigervnc) + if [ -n "${version}" ] ; then echo "TigerVNC ${version}" ; fi + version=$("${_current_dir}/version_of.sh" screenshooter) + if [ -n "${version}" ] ; then echo "xfce4-screenshooter ${version}" ; fi + version=$("${_current_dir}/version_of.sh" ristretto) + if [ -n "${version}" ] ; then echo "Ristretto ${version}" ; fi + version=$("${_current_dir}/version_of.sh" novnc) + if [ -n "${version}" ] ; then echo "noVNC ${version}" ; fi + version=$("${_current_dir}/version_of.sh" websockify) + if [ -n "${version}" ] ; then echo "websockify ${version}" ; fi + echo "Firefox ${firefox}" + ;; + -f ) + env | grep "FEATURES_" | sort + ;; + esac + shift + done + else + ### example: ubuntu20.04.1-firefox81.0 + sticker="ubuntu${ubuntu}"-"firefox${firefox}" + echo "${sticker}" + fi +} + +main $@ diff --git a/docker/xfce-firefox/ubuntu-vnc-xfce-firefox-plus.jpg b/docker/xfce-firefox/ubuntu-vnc-xfce-firefox-plus.jpg new file mode 100644 index 0000000000000000000000000000000000000000..749c92580532690c79589f4b25a2dd5f86792ec0 GIT binary patch literal 67981 zcmeFZ2|QKp*EhbAAyTPhEK$f5GNpv0WKL$vkjhNR6q$|`)k&rdr9y_JLWN{Xkw^*0 zR4S5rh|J?T=fC!$ySkt0_j}&w^ZuXbed_)k_t|@2!@AbBhVNSI+K2p}`~_LBrKYKd zP*G7K$KXGN+_k=4)z{GuL3DHw5d=XPkX2NB5o-8G3l~}!9FbM aNrLI{&3(A2mUv5V4tha8CW-M6b%JO zU;r;9MXmbl`{S5s%6A$$Sp {BM+=KWqNOfj=Dh!+}2>_``vp z9FW>6wNqYFN`B`qUP&2wS@^OW`Pc3t$Uejsu|ZG(LhfQ>ckuE$B`+c2>M4HQ#_fcy zxV4*$gzxcF5|ZLOB@hLy@2TU~&bD5>Cv5E f^O=Wd<>YP%sb#T=1 z^RPAaJ7i?-=WM;lMi8sS%&6ci@9T2P#n$UMudmBVS5J9g#ch<)<>5PeTVk7%f`^Tr zyuksrl@@TNxNU_NA0HoaA8Bzn4|@s8J$v>@?39v_k`jX!VxDJQy^i~exq9-g3~<2K z)7r!Fl$WEMD=#|W@e^*|UW(hiy&Y}j?T*{Yp0Kfz6+3ZU+D1%L(&o6>aT{q#F&k-V z8#!6Y-BNavC$_CjZ)5$}?5DgvPEzK!v6iqsY3pL^>g5UCkd)Xau}t)T)ttbhzb5@x z*$-=kHu5SSw#U6}55PwW-B2+}DY2cqjDBpgxSY%`1&P14Q; fXG3=zXTL| z^8R1=_h*uSiphW2^@m;m6bJsP#($*i54-*;4*XM%|47&WFn0X}xwfu=Y<&R2l0PCU z2t6$=9qlT5I$AmgdU^&%7AC+LjI8U{uVLX}<>KUE 1RND}07AhJR zD)LK&2MUg~P@+Vulq>(JsA*Qw($O=lW@Lf}1?v%NDjFK ew#Z+>TL9F2EP4|Ua%T8e&?4y;SsW$k&T^$lS^Q`ppdYLjO;GC-FxI! z4ydZBYiMd28X23I9zJ4bZDVU^@8Ia<>E(Ue$M=lix$~i67cO4H$6Sq#i%+ yR1-K=|$^YROx6h18~uBd!j^{Tq&buFQ(xuv!3{fG9huiZVpef )IRW`VOd4HRg!MQK7IP*?i;sBon^r6 zkG}or#cDojgYT>-JQ^9<_+`2T#?hrwR`!oAEaX46vcDGgb6xGo8X79tJQ@}Ri%jEa zeMKwUj#7OmR<(uYpUJ#&@W~m0n2PQ8)*E78#=YjBOw7CQ(8=t@o&2%bEmWpcdNlAc zlY>v7991IWJI~V9NM w?O-_r9oYn6se>M`iujw0U<51gW#|)J(Z$2h0KKv;5 zAfi*%BJm>`Ilr!gXG&xsc~1NS8M&0pR2Zq>T53PT!|W?qSsXGHukA_9P$=A>_~4{g zn3N=)6k|*YtL|ox-LqIm=k3E?&n{;VvonNQZf7dV>e*_n8EW}HDcD=4OSJm>< wvPYm$oFYrkt2syE12DVH}ks#G+(#h-coiv)q+8(X>;2N(kQe1*TXg%jN$6} zUw0k*6n~l}`rNHr9Wr8dy356d=;Y1w{p_3yDb#W!8KG?;BjYl--zjM|x!%3$jqFC> zXWAStqh3AD$D9w_(D5EIs;Knj+|0>G70cXvkzse8b29gksXYB 2iRm^O`Red@E *0_j2SE+p$BYG0@*#G4`YR>Cvn1o1Jb;9UlE0lSZp!*BPJ}vNv1f{heV4F)^-n z`5)>rNnVo*)?O!X*LE2PGsX9>>M & zGMsKjUdf-6F+WlesN SY3k-JGu;(+4iV!*JFKa^Fqm5;9*`4LXlE1uZ zd-9O2eL&x9sJ_VJ;~Q}nd8%vGZ;up5M@)S?HHaHlu_CR X|xIV`vM(W zye$t78#pGeFPO|8x$@~%FX!1ERVVfpgvnt73U_~O=*yqFq9tan`ndVqi^I9RnhkP# zoGJ)TUe1(MOh&FU-zv`?HkAGkR@KzP*PQ-{Pp!D1pr~e>c8SR?$xkjv*7tY%bXg>a z2AJNp800#d_BGo|^O85Wy!QAiwhfiNug)?(io4@oG1kv(&&Tm1t$dnza<5WY{St4` zdNOj`^Z*%o;e}n&`Mb=@a+gO2?Db@BzH~+gXA`z3Bf?+!Yt)W#69v8$yB*I%kqw`Y zZ4Qs|{iqqg*WqOUO)IPUEXP&FfzJa6jJU@~)Tf_i>p&G}4{8C4~R)Vwfp+wv_){ z!uKcmYL3@UU$Ki~$Bxd8k`WS%gEzNQJC#Q<_p2 r>b9X>(KNO+*5f{&A@Y_FdI8OUf9RgPAU&6?{WH@+WiXy zpf@0Y;i7EKH`%BK?ri_-aV;Rnt^*^ 5zhWn-zvGCEi9E~Z>IZ|E zUXYO~5eM9|X8=wwj|3KtqVE5H4OKxyveo&^rt?tE?YkELJ?Elk&(%zodeUC=DLp#+ zCElapT5cPH!}+0BzF1PI4&0=;0@-p^ VGo7{(J7?AF5D8^+&EyOZ?x|(EJh6KO*|y+!y{g6VXSq>$v7jHOgbE zjmO0!t$o-O-uT~`ON*AG;xsv?wvT?mfg1ZC7(J)a=&y?FUT*Q3S(}$R6r|QEH)5(O zmr%0%bN)?xdd?}?3}p@g$-jAX2<(3M Mcp-}izhMAEpti@gQL@E@lq&NY#ddA4AI|JY!q ze>b`9eSeO=av}b<#4VpQcg%GaZtNfPxpX7~L2Rx*=g2OmAkhB;yXQ1o#Fi}(@;b#r zowaAf>H~&%Cq|8^*Bm;fbuNkX%qp5NPQ!Nt9b!+%%NDA;KF_fEc|X@NI}&~HveeCj z)V1o16KldZZ{;6VX14kd_61dhIozu!-`jm5h-aI5#J^J|>r=YB+HGTu)^j16V5A#k zl%z;TVxqrVEizf+2KrKimCF8>!tkBFxFnG~=k}_wO*Fm!!C;|jo@K>`4j *>?*&8tJ&UGPLwq3>?rTxxpg4zZMHuvr%;)3J%8i$ z{ma}NT=u@`U}zbcHvf7s=JN~h{3km(N5xq*5x*pQWj|AYmoA62IdA&V?YEZhPUSZx zdLg@3?N_W+oU4~DE5nsy<>hi`FZ3I71r(OJl94uTc98^4HDU9@rA;?IeC13Nb+m>} zTBgdhMoAT$HY9NE+4X|Y=Y*NWUWum~9&&5X3|3(^=Wxy$+L^`mY#*JSpJw7W9mjYS zya zF7KG^pZK>O`MHimBhH_F)c4+<+pl J$H99uiPiqP4n zJE6|Q6EdyseAio4$B$v!KF0IRUdP4M>$V@FqUW#gPZg?&scRTzPAs}Jr?QAu{r)V; zt+aDa{j>Soo!#F!LNto)d&$U=B%)-eEa4|tnhw?0U~@~WN*i+0TV!?Ab(^16d;1?} zPB%D1t-CeN@vvsdsm@_Pp3&+4%hH2NK9^2 qwA^XRt- zFCTP6)uu_`mj*55KlRHxyXfkUGr!7Ccl>r&w)NJG-4%fY!u%)eSoYRz(!KU2I%fBm zmJ*&d?*-3|lw$9FG#@f~GSjHS@3Zp~Uu+7Gq)ClJ_@w!!w#CZHG(R%p8|39xINi2X zY2LXoNIGzO=HZbK)z0>7PS1Q#i4aOv&f+>7jKJ$4$1QBi*L7X4EcT9TO_Q#?<4`E? zoX__1wNSJ*ovPm9o--EWoAxX%2BIR-NMZ6`GGa+a-nySwxL02(e<9*dTSSpNU!_<^ zTt2(0Jl}`(m`c&Qy8NEJ?MG;Ax*k8b-t2A09)f!`%`HE6I?ioIXw-U9>1qZsf_*Yv z{dB$L_sZIy{+kik`tMUThq8i9e??ki(1mRQG#vTk2bu2fk{w776Kka25#91yPkM5l zlqOGMN43)pgYO4@I`|u9eaDjMnhpo1QgPUnGHpt=Pmaw^oa0lFq*q{R{<(RCO>N^# zK6~mmR<=Jo|NVXY@F~sP<~R2_3q-i`Mb24Ip1+}$yKk}VqcUfGou$BbbZZ7EG*PqR zb$&7cF%zaJBW3Rfs2tLN(w#z^dUcuklv#uS^t(mb&p&+mq3i#}^5ShUe7I?cEz8lN zUGW6gPa7OtR&RMKm`N8bt`EjDX25EStEv3EF!ojCoTit=0<&Z1945J2naj(>eu=-B zok*8Iw#2AAo<`bW$wWG5=0l Ed`1yh|13}$4cbDE5BVSl?qic}3rZB4j=t &ac==!qKajlduk9QwWJ|sdh6Ajdjnm_%KGLz~rrUVhg-1x;tBl!kD?bCm{ zADz#|smM7E1<`v09k>r&`{{K+S76H70JOI+35Z+36X3##nKEpP;2A(_Sr2vMq7 z@fU;k?t5P}08v0PUfG-K7u9FHV|OK;u1m6yKP%_*`jz`lo7T90dks{#avVK}*_dpZ zm!9l=&AX_rEXf~ztWPH39H$`X@fbSy5EU`G?-|(zq-6gT48bnXsL(cSYj6F@OrmxQ z@2S=AKkFq)F^Rg4{e?aL#t5DbzOy7P^-H)BF>f-GmWWsICnExUFUx1xipfZ0ohlM& z`^7WzLJ&6@d1zcn!kaZG>xVE|?Rh {_oCOr#DljaslhfANAQ jfLd-V_yHQ@gXPhcr0LHm@eXF+y6$dFqB{qN1otX>+_K-Qcw9(_0zqYxp*; zW+r95-mz >>3$dFXlmFpFwj#O_s-W^_Z zjAnwsbSr;$eS3v%QQ~gvRn!wZ^;Yku5p0gaa;+M24d=M(t2{sP(RFoo$1CaTgMFoU zwA)%rWxsCHbTxC{D?F03%|Fn rkb0fc6yj352|_v_j32Ux|rf?-!n!M2DhB; zKXPI)=iHk e9~jzI}{@N z@yO^F2G`>;4wKJhqS!1pZ;nVy>|0{L`@(CswYBNB$3uqq?~2cLR8$q(?8uRGoe#1d zka{|7{-iC)^|lPQoy~LP^Ww#X4cpf$S(i=?_- 6_I&R@}@CHUxOMiltNv$5lnkjRX@=OM`UQb)t2g%Ji$>) zMsmg=9nR&z7^|-;NsG}}W}6zDTfi-J$&v6*Sth?;D5H-lO}b$u#cHC@WpGw8_l%#C zk)Cz#08zh!-L| AQv8C4QdoB~xVNTm3hQ zN0664pj0_iFa2hMM3C%t?RMQo?2yDyzqzCkOGb2x!kDh}GGD$CdgXfe)=QP^552G9 zpQ)D_5xrHwx_M)jr`zTkLV82(?e3UeYjVSZF}P??nN5t zQa|0$=6?9|FrQ($^TmJzVuW4AIHCP*msuj;yd&&-G$ghA1xI#0SL{WH1XF90z)W$X z_UV_l`U*wVdAP^?LY^PbwMSWejx>C9Lw7O2^vT4LZ(=iXaR+_5p~i<<+&iqJ*5c~5 zc-J+>tz^drdc!F`{3Nr!PLEH*Lcs9aa}pQ7TpvAf{OiO^s-wpk+D+dfqkAl_RP)Kc zpOatEZfQY^%ojCAD?U0gab>nAyxFh$p882s+$V(It$@l?o3ue^jT5squ^^N9$jaKB zn5FQ%j)p= zf%nJs{0PM@o$Hix#e$t94kXK~by$ZB)*jmPZj;~|alc!v{ba-~s^f!dH@BU+5bp7p znAO>tG3|SAgqXkGL#26amG6G+#ifGwb| !=ho{6JPN=F~*5q>tEezH(v8Wfm#De>bn=PuPi@MX`-TI;)Q** zQGMpMb?v!9gZdl$vo_Pcf3NsTh~?vF%a8BdUwityv*xpem*(wO)gRLQVr;JCuTh?# zI8<%?xTx?P@npj%zI5E!&fPp$tcS)2<=$j}v>GaWc#ic^ariEi2Af!$+Bi HD*o|iU?6d1147m?2tWDyL5! cli^J-a z7M5PvJt@|Egk9-6J*!<2miE(;Ayc!QN3_%D+vMstYCGGWin(lKyp<-7pIsrw&;4vv zQO@JD*F5Ixl|zOc1e;B^hZtgV`CT8SoeN=#&JXf_!eC3Q!5bd3w~Z# gh2j%OWMX{G M{Dnx z_yUWt)Yik>*F26$>!S%94v&aC^om(>hXVVV?1N(2v;}W<6%v>kMK`n3o<%l>Eqo0w z`l2KcX|799FK7IW8)!|9L9p@p2x|UBl>nrmZ`C92*Fqm`hdfK<+yyNK-%e4$d zLhI*uk&d330@ovL+#^574kdjp6+AG0sKl-7^DYiq?Tg(J1b$WKir`=>lN+zL@N>&v zPF@@;tLfz^WEBwj>_kRt=8O8TZE;l73rxCf9#HR{pC4A+BK9req{B}7={rtr`a@=x zE#bZKqIZw73n?FakiOZzT=vViZi$UEt*$sp5-aC;GQPyw)an`;VZ3nlgnw=s8HrA< z{~rI?U@>7nY25RUiudih3=IOq_9xDEwtS}yN<7v|-t;%Vw$ RSD z(|YW$q+);VXbs$`UOKmkTitHuK}MtpoJ9MR|IJlmA3aiR>n80ZmY@G7QG~lbCCfTl zzqCC_1l(UsTOYO}^0%%lJmDpER-8`wRQ`5>3qRja+K6SvH8>4V@^q>H)^+5huJ;@` zUYuLkUhPq a#&XgWc8(d2Gj7ygWT&7>> 4xMDgk7tQ45>C3Otu+4uKI88<%IeOqIf`rZf&9jmGm$e_$jIz%GV&ab zZ_gz@ByDZuKkf6(&Th{R>;0P3gSso=RbpkjccXYXO;|XcJHG^AT@&D_+pyK-JV3dt zOTuL2?+~*z^(pon(V2w9PHX@a{c)jfiG=HcBf5-#H&Fu%K1+dE;;9>CL{-)(hb2HI zXKSsM)J>LXuC)v=xD|!5zfSs}pQl6Lf@g*V>3VGP{AzF>zfkvgL79Rx0Kevf;wsjy zA3n>-)Yq;d5Rm_Z@Alv*PG0xl8DLB(XWb&sjEp4LFP%^BQvY?{zdJ3TSW|jpc{Z-T zpR`{WVuoM4{SJQ>D_?X@&?k^el8Lm=DY>_fk6T?5Ysh$ZUq -8d+%f<4>QjRj^^rk5D&2QSz9ue?=zo-n=&&p