├── .dockerignore ├── ubuntu-vnc-xfce-firefox-plus.jpg ├── src ├── firefox │ ├── profiles.ini │ └── profile │ │ └── put_your_profile_content_here.readme.txt ├── home │ ├── Desktop │ │ ├── FF Profile Manager.desktop │ │ ├── Copy FF Preferences.desktop │ │ └── firefox.desktop │ └── config │ │ └── xfce4 │ │ ├── panel │ │ ├── launcher-21 │ │ │ └── 15564438881.desktop │ │ └── launcher-22 │ │ │ └── 15564439112.desktop │ │ └── xfconf │ │ └── xfce-perchannel-xml │ │ └── xfce4-panel.xml ├── patch_vnc_startup.txt ├── patch_vnc_startup.sh ├── firefox.plus │ ├── user.js │ ├── copy_firefox_user_preferences.sh │ └── accetto.svg ├── startup │ └── version_sticker.sh └── create_user_and_fix_permissions.sh ├── hooks ├── push ├── build ├── env └── test ├── .gitignore ├── utils ├── example-secrets.rc ├── util-refresh-readme.sh └── util-hdx.sh ├── .gitattributes ├── Dockerfile-plus-profile ├── Dockerfile-plus-preferences ├── local-building-example.md ├── Dockerfile ├── LICENSE ├── CHANGELOG.md └── README.md /.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !src 3 | *.log 4 | *.md 5 | *.sh 6 | .developer* 7 | debug* 8 | scrap* 9 | TODO* 10 | -------------------------------------------------------------------------------- /ubuntu-vnc-xfce-firefox-plus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accetto/ubuntu-vnc-xfce-firefox-plus/HEAD/ubuntu-vnc-xfce-firefox-plus.jpg -------------------------------------------------------------------------------- /src/firefox/profiles.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | StartWithLastProfile=1 3 | 4 | [Profile0] 5 | Name=default 6 | IsRelative=1 7 | Path=profile0.default 8 | Default=1 9 | -------------------------------------------------------------------------------- /hooks/push: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | 3 | . ./hooks/env 4 | 5 | if [[ -n "${BASETAG}" ]] ; then docker push ${DOCKER_REPO}:${DOCKER_TAG} 6 | else 7 | echo "Nothing to push!" 8 | exit 1 9 | fi 10 | -------------------------------------------------------------------------------- /src/firefox/profile/put_your_profile_content_here.readme.txt: -------------------------------------------------------------------------------- 1 | Copy your Firefox profile content into the folder './src/firefox/profile' before building the image. 2 | You have to modify the 'Dockerfile-plus-profile' if you use another source folder. 3 | -------------------------------------------------------------------------------- /src/home/Desktop/FF Profile Manager.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Type=Application 4 | Name=FF Profile Manager 5 | Comment=Open Firefox Profile Manager 6 | Exec=firefox -P 7 | Icon=accetto 8 | Path= 9 | Terminal=false 10 | StartupNotify=true 11 | -------------------------------------------------------------------------------- /src/patch_vnc_startup.txt: -------------------------------------------------------------------------------- 1 | ### Patch #1 2 | ### Issue #3: Default Firefox profile not initialized on external volumes (bind mounts) 3 | if [[ -d "$HOME/.mozilla" ]] ; then 4 | if [[ ! -d "$HOME/.mozilla/firefox" ]] ; then 5 | cp -r $HOME/firefox.plus $HOME/.mozilla/firefox 6 | fi 7 | fi 8 | ### End-of-patch #1 9 | -------------------------------------------------------------------------------- /src/home/Desktop/Copy FF Preferences.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Type=Application 4 | Name=Copy FF Preferences 5 | Comment=Copy user.js into Firefox profiles 6 | Exec=/home/headless/firefox.plus/copy_firefox_user_preferences.sh 7 | Icon=accetto 8 | Path= 9 | Terminal=true 10 | StartupNotify=true 11 | GenericName=Copy FF Preferences 12 | -------------------------------------------------------------------------------- /src/patch_vnc_startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ### every exit != 0 fails the script 3 | set -e 4 | set -u 5 | 6 | TARGET="$STARTUPDIR/vnc_startup.sh" 7 | PATCH="./patch_vnc_startup.txt" 8 | 9 | LINE=$(grep -n 'set -u' $TARGET | cut -d ":" -f 1) 10 | LINE=$(($LINE+1)) 11 | 12 | { head -n $LINE $TARGET; cat $PATCH; tail -n +$LINE $TARGET; } > "$TARGET".patched 13 | mv -f "$TARGET".patched "$TARGET" 14 | -------------------------------------------------------------------------------- /hooks/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | 3 | . ./hooks/env 4 | 5 | if [[ -n "${BASETAG}" ]] ; then 6 | 7 | docker build $@ \ 8 | -f ${DOCKERFILE_PATH} \ 9 | --build-arg BASETAG="${BASETAG}" \ 10 | --build-arg ARG_REFRESHED_AT="${TODAY}" \ 11 | --build-arg ARG_VERSION_STICKER="${VERSION_STICKER}" \ 12 | --build-arg ARG_VCS_REF=`git rev-parse --short HEAD` \ 13 | -t ${DOCKER_REPO}:${DOCKER_TAG} . 14 | else 15 | echo "Build request not recognized: ${SOURCE_BRANCH}" 16 | fi 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # blank lines are ignored 2 | # lines starting with '#' are ignored 3 | # starting patterns with '/' disables recursivity 4 | # ending patterns with '/' specifies directories 5 | # starting patterns with '!' negates them 6 | # standard glob patterns (shell paterns) work: 7 | # '*' matches zero oro more characters 8 | # '?' matches a single characters 9 | # '[abc]' matches the characters inside the brackets 10 | # '[0-9]' matches the characters inside the brackets 11 | # '**' matches nested directories (e.g. 'a/**/z') 12 | # recommended files on 'https://github.com/github/gitignore' 13 | 14 | .vscode 15 | .developer* 16 | .secret* 17 | *.log 18 | avanti* 19 | debug* 20 | scrap* 21 | secret* 22 | TODO* 23 | -------------------------------------------------------------------------------- /utils/example-secrets.rc: -------------------------------------------------------------------------------- 1 | ### This files configures the environment (including secrets!) for the local builder utility (builder.sh). 2 | ### You should source this file yourself before using the local builder utility. 3 | ### Rename the file to "secrets.rc" (or similar) and **make sure** that the '.gitignore' and '.dockerignore' files 4 | ### contain the 'secret*' exclusion pattern! 5 | 6 | ### Required only for publishing README on Docker Hub. 7 | ### These values can be also provided or overriden through the utility input arguments. 8 | ### !!! REAL SECRETS !!! 9 | ### warning! this credentials are valid for all Docker Hub repositories of the same owner! 10 | export DOCKERHUB_USERNAME="xxxxxx" 11 | export DOCKERHUB_PASSWORD="xxxxxx" 12 | -------------------------------------------------------------------------------- /hooks/env: -------------------------------------------------------------------------------- 1 | ### hooks/env 2 | 3 | SOURCE_BRANCH=${SOURCE_BRANCH:-$1} 4 | DOCKER_TAG=${DOCKER_TAG:-$1} 5 | if [[ -n "$1" ]] ; then shift ; fi 6 | 7 | DOCKERFILE_PATH=${DOCKERFILE_PATH:-./Dockerfile} 8 | DOCKER_REPO=${DOCKER_REPO:-accetto/ubuntu-vnc-xfce-firefox-plus} 9 | 10 | BASETAG="" 11 | TODAY=$(date +%Y-%m-%d) 12 | 13 | ### Warning! The values must be explicit strings (used by utils). 14 | VERSION_STICKER_LATEST="ubuntu18.04.6-firefox98.0" 15 | 16 | VERSION_STICKER="${VERSION_STICKER_LATEST}" 17 | 18 | case "${DOCKER_TAG}" in 19 | 20 | latest) 21 | BASETAG="latest" 22 | ;; 23 | 24 | dev | dev-preferences | dev-profile) 25 | BASETAG="dev" 26 | ;; 27 | 28 | *) 29 | BASETAG="" 30 | ;; 31 | esac 32 | -------------------------------------------------------------------------------- /hooks/test: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | 3 | . ./hooks/env 4 | 5 | it=$1 6 | it=${it:+-it} 7 | 8 | vars=($(docker run ${it} --rm ${DOCKER_REPO}:${DOCKER_TAG} printenv VERSION_STICKER STARTUPDIR | tail -n2)) 9 | 10 | expected="${vars[0]}" 11 | 12 | startup="${vars[1]}" 13 | startup="${startup%%[[:space:]]}" 14 | 15 | ### Windows only: VSC with GitBash requires the first slash doubled 16 | [[ -n "${WINDIR}" ]] && startup=/${startup} 17 | 18 | actual=$(docker run ${it} --rm ${DOCKER_REPO}:${DOCKER_TAG} ${startup}/version_sticker.sh | tail -n1) 19 | 20 | expected=${expected%%[[:space:]]} 21 | actual=${actual%%[[:space:]]} 22 | 23 | if [[ -n "${it}" ]] ; then 24 | [[ "${actual}" == "${expected}" ]] && echo 0 || echo 1 25 | else 26 | [[ "${actual}" == "${expected}" ]] && exit 0 || exit 1 27 | fi 28 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # GitHub language detection 2 | # linguist-language, linguist-vendored, linguist-documentation, linguist-generated, linguist-detectable 3 | * linguist-documentation=true 4 | Dockerfile linguist-documentation=false 5 | Dockerfile linguist-language=Dockerfile 6 | Dockerfile linguist-detectable=true 7 | 8 | # Set default behaviour, in case users don't have core.autocrlf set. 9 | * text=auto 10 | 11 | # Explicitly declare text files we want to always be normalized and converted 12 | # to native line endings on checkout. 13 | *.c text 14 | *.h text 15 | *.sah text 16 | *.suite text 17 | *.inc text 18 | *.js text 19 | *.json text 20 | 21 | # Declare files that will always have CRLF line endings on checkout. 22 | *.sln text eol=crlf 23 | 24 | # Denote all files that are truly binary and should not be modified. 25 | *.png binary 26 | *.jpg binary 27 | -------------------------------------------------------------------------------- /src/firefox.plus/user.js: -------------------------------------------------------------------------------- 1 | // Add the preferences you want to force here. 2 | // They will be forced for each session, but only in profiles containing this file. 3 | 4 | // Disable WebRTC leaks as explained in https://ipleak.net/#webrtcleak 5 | // Be aware that this has impact on some applications, e.g. some messengers. 6 | // user_pref("media.peerconnection.enabled", false); 7 | 8 | // Fixing "Gah. Your tab just crashed." 9 | // Disabling Firefox multi-process through preferences doesn't work since version 68.0. 10 | // user_pref("browser.tabs.remote.autostart", false); 11 | // user_pref("browser.tabs.remote.autostart.2", false); 12 | // Disabling the Firefox multi-process must be done by setting the environment variable 13 | // MOZ_FORCE_DISABLE_E10S. Note that any value means 'yes'. Both following settings 14 | // will disable the multi-process feature: 15 | // MOZ_FORCE_DISABLE_E10S=1 16 | // MOZ_FORCE_DISABLE_E10S=0 17 | -------------------------------------------------------------------------------- /src/home/config/xfce4/panel/launcher-21/15564438881.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Name=Firefox Web Browser 4 | Comment=Browse the World Wide Web 5 | GenericName=Web Browser 6 | Keywords=Internet;WWW;Browser;Web;Explorer 7 | Exec=firefox %u 8 | Terminal=false 9 | X-MultipleArgs=false 10 | Type=Application 11 | Icon=firefox 12 | Categories=GNOME;GTK;Network;WebBrowser; 13 | 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; 14 | StartupNotify=true 15 | Actions=new-window;new-private-window; 16 | X-XFCE-Source=file:///home/headless/Desktop/firefox.desktop 17 | 18 | [Desktop Action new-window] 19 | Name=Open a New Window 20 | Exec=firefox -new-window 21 | 22 | [Desktop Action new-private-window] 23 | Name=Open a New Private Window 24 | Exec=firefox -private-window 25 | -------------------------------------------------------------------------------- /src/home/config/xfce4/panel/launcher-22/15564439112.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Name=Firefox Web Browser 4 | Comment=Browse the World Wide Web 5 | GenericName=Web Browser 6 | Keywords=Internet;WWW;Browser;Web;Explorer 7 | Exec=firefox %u 8 | Terminal=false 9 | X-MultipleArgs=false 10 | Type=Application 11 | Icon=firefox 12 | Categories=GNOME;GTK;Network;WebBrowser; 13 | 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; 14 | StartupNotify=true 15 | Actions=new-window;new-private-window; 16 | X-XFCE-Source=file:///home/headless/Desktop/firefox.desktop 17 | 18 | [Desktop Action new-window] 19 | Name=Open a New Window 20 | Exec=firefox -new-window 21 | 22 | [Desktop Action new-private-window] 23 | Name=Open a New Private Window 24 | Exec=firefox -private-window 25 | -------------------------------------------------------------------------------- /src/startup/version_sticker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ### @accetto, September 2019 3 | 4 | ubuntu=$("${STARTUPDIR}/version_of.sh" ubuntu) 5 | firefox=$("${STARTUPDIR}/version_of.sh" firefox) 6 | 7 | case "$1" in 8 | -v) 9 | echo "Ubuntu $ubuntu" 10 | echo "Firefox $firefox" 11 | ;; 12 | -V) 13 | mousepad=$("${STARTUPDIR}/version_of.sh" mousepad) 14 | vim=$("${STARTUPDIR}/version_of.sh" vim) 15 | nano=$("${STARTUPDIR}/version_of.sh" nano) 16 | tigervnc=$("${STARTUPDIR}/version_of.sh" tigervnc) 17 | novnc=$("${STARTUPDIR}/version_of.sh" novnc) 18 | websockify=$("${STARTUPDIR}/version_of.sh" websockify) 19 | curl=$("${STARTUPDIR}/version_of.sh" curl) 20 | git=$("${STARTUPDIR}/version_of.sh" git) 21 | jq=$("${STARTUPDIR}/version_of.sh" jq) 22 | echo "Ubuntu $ubuntu" 23 | echo "Mousepad $mousepad" 24 | echo "VIM $vim" 25 | echo "GNU nano $nano" 26 | echo "TigerVNC $tigervnc" 27 | echo "noVNC $novnc" 28 | echo "websockify $websockify" 29 | echo "curl $curl" 30 | echo "Git $git" 31 | echo "jq $jq" 32 | echo "Firefox $firefox" 33 | ;; 34 | *) 35 | ### example: ubuntu18.04.3-firefox_68.0.2 36 | sticker="ubuntu$ubuntu"-"firefox$firefox" 37 | echo "$sticker" 38 | ;; 39 | esac 40 | -------------------------------------------------------------------------------- /utils/util-refresh-readme.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ### @accetto, October 2019 3 | 4 | ### This script updates version sticker badges in README files. 5 | ### The script is intended for local use before publishing the repository. 6 | 7 | ### where to start processing 8 | searchdir=$1 9 | searchdir=${searchdir:-..} 10 | 11 | if [[ ! -d ${searchdir} ]] ; then 12 | echo "Folder '${searchdir}' not found!" 13 | exit 1 14 | fi 15 | 16 | cd ${searchdir} 17 | searchdir=$(pwd) 18 | 19 | ### process only folders containing 'README.md' and 'hooks/env' files 20 | find "${searchdir}" -type f -name "README.md" | while read readme_file ; do \ 21 | 22 | dir="$(dirname ${readme_file})" 23 | env_file="${dir}/hooks/env" 24 | 25 | if [[ -f "${env_file}" ]] ; then 26 | 27 | echo "${dir}" 28 | 29 | sticker_lines=$(grep -E '^\s*VERSION_STICKER_[A-Z]+="[^$]+' "${env_file}") 30 | echo "${sticker_lines}" 31 | 32 | for sticker_line in ${sticker_lines} ; do 33 | 34 | arr=(${sticker_line//'='/' '}) 35 | sticker_label=${arr[0]} 36 | sticker_value=${arr[1]} 37 | sticker_value=${sticker_value//'"'/} 38 | 39 | ### if using 'shields.io' static badges 40 | # sed -i "s/^\s*\(\[badge\-$sticker_label\][^&]*\&[^=]*=\)\([^&]*\)/\1$sticker_value/" "$readme_file" 41 | ### if using 'badgen.net' static badges 42 | sed -i "s/^\s*\(\[badge\-${sticker_label}\]:\s*https:\/\/[^/]*\/badge\/[^/]*\/\)\([^/]*\)/\1${sticker_value}/" "${readme_file}" 43 | done 44 | fi 45 | done 46 | -------------------------------------------------------------------------------- /Dockerfile-plus-profile: -------------------------------------------------------------------------------- 1 | # ./hooks/build dev-profile 2 | # ./hooks/test dev-profile 3 | 4 | ### Example: Build and test 'dev' tag locally like 5 | ### ./hooks/build dev-profile 6 | ### ./hooks/test dev-profile 7 | ### or with additional arguments 8 | ### ./hooks/build dev-profile --no-cache 9 | ### ./hooks/test dev-profile 10 | ### or using the utility 11 | ### ./utils/util-hdx.sh Dockerfile 3 12 | ### ./utils/util-hdx.sh Dockerfile 4 13 | ### The last output line should be '+ exit 0' 14 | ### If '+ exit 1' then adjust the version sticker 15 | ### variables in script './hooks/env' 16 | 17 | ARG BASETAG=latest 18 | 19 | FROM accetto/ubuntu-vnc-xfce-firefox-plus:${BASETAG} 20 | 21 | ### Arguments can be provided during build 22 | ARG ARG_MOZ_FORCE_DISABLE_E10S 23 | ARG ARG_REFRESHED_AT 24 | ARG ARG_VCS_REF 25 | ARG ARG_VERSION_STICKER 26 | ARG ARG_VNC_BLACKLIST_THRESHOLD 27 | ARG ARG_VNC_BLACKLIST_TIMEOUT 28 | ARG ARG_VNC_RESOLUTION 29 | 30 | LABEL \ 31 | any.accetto.description="Headless Ubuntu VNC/noVNC container with Xfce desktop and Firefox with profile" \ 32 | any.accetto.display-name="Headless Ubuntu/Xfce VNC/noVNC container with Firefox profile" \ 33 | version-sticker="${ARG_VERSION_STICKER}" \ 34 | org.label-schema.vcs-ref="${ARG_VCS_REF}" \ 35 | org.label-schema.vcs-url="https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus" 36 | 37 | ENV \ 38 | MOZ_FORCE_DISABLE_E10S=${ARG_MOZ_FORCE_DISABLE_E10S:+1} \ 39 | REFRESHED_AT=${ARG_REFRESHED_AT} \ 40 | VERSION_STICKER=${ARG_VERSION_STICKER} \ 41 | VNC_BLACKLIST_THRESHOLD=${ARG_VNC_BLACKLIST_THRESHOLD:-20} \ 42 | VNC_BLACKLIST_TIMEOUT=${ARG_VNC_BLACKLIST_TIMEOUT:-0} \ 43 | VNC_RESOLUTION=${ARG_VNC_RESOLUTION:-1024x768} 44 | 45 | ### Be sure to use root user 46 | USER 0 47 | 48 | WORKDIR ${HOME} 49 | 50 | ### Copy pre-configured Firefox profile 51 | COPY [ "./src/firefox/profile/", "./.mozilla/" ] 52 | 53 | ### Change owner 54 | RUN chown -R ${VNC_USER} ./.mozilla 55 | 56 | ### Switch to the non-root user 57 | USER ${VNC_USER} 58 | 59 | ### Issue #7 (base): Mitigating problems with foreground mode 60 | WORKDIR ${STARTUPDIR} 61 | -------------------------------------------------------------------------------- /Dockerfile-plus-preferences: -------------------------------------------------------------------------------- 1 | # ./hooks/build dev-preferences 2 | # ./hooks/test dev-preferences 3 | 4 | ### Example: Build and test 'dev' tag locally like 5 | ### ./hooks/build dev-preferences 6 | ### ./hooks/test dev-preferences 7 | ### or with additional arguments 8 | ### ./hooks/build dev-preferences --no-cache 9 | ### ./hooks/test dev-preferences 10 | ### or using the utility 11 | ### ./utils/util-hdx.sh Dockerfile 3 12 | ### ./utils/util-hdx.sh Dockerfile 4 13 | ### The last output line should be '+ exit 0' 14 | ### If '+ exit 1' then adjust the version sticker 15 | ### variables in script './hooks/env' 16 | 17 | ARG BASETAG=latest 18 | 19 | FROM accetto/ubuntu-vnc-xfce-firefox-plus:${BASETAG} 20 | 21 | ### Arguments can be provided during build 22 | ARG ARG_MOZ_FORCE_DISABLE_E10S 23 | ARG ARG_REFRESHED_AT 24 | ARG ARG_VCS_REF 25 | ARG ARG_VERSION_STICKER 26 | ARG ARG_VNC_BLACKLIST_THRESHOLD 27 | ARG ARG_VNC_BLACKLIST_TIMEOUT 28 | ARG ARG_VNC_RESOLUTION 29 | 30 | LABEL \ 31 | any.accetto.description="Headless Ubuntu VNC/noVNC container with Xfce desktop and Firefox with preferences" \ 32 | any.accetto.display-name="Headless Ubuntu/Xfce VNC/noVNC container with Firefox preferences" \ 33 | version-sticker="${ARG_VERSION_STICKER}" \ 34 | org.label-schema.vcs-ref="${ARG_VCS_REF}" \ 35 | org.label-schema.vcs-url="https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus" 36 | 37 | ENV \ 38 | MOZ_FORCE_DISABLE_E10S=${ARG_MOZ_FORCE_DISABLE_E10S:+1} \ 39 | REFRESHED_AT=${ARG_REFRESHED_AT} \ 40 | VERSION_STICKER=${ARG_VERSION_STICKER} \ 41 | VNC_BLACKLIST_THRESHOLD=${ARG_VNC_BLACKLIST_THRESHOLD:-20} \ 42 | VNC_BLACKLIST_TIMEOUT=${ARG_VNC_BLACKLIST_TIMEOUT:-0} \ 43 | VNC_RESOLUTION=${ARG_VNC_RESOLUTION:-1024x768} 44 | 45 | ### Be sure to use root user 46 | USER 0 47 | 48 | WORKDIR ${HOME} 49 | 50 | ### Copy the file with default user preferences. 51 | ### The preferences will be forced for each session, but only in the profile containing the file. 52 | ### Make also a backup copy of the file 'user.js'. 53 | ### The VNC user ('headles:headless' by default) will get permissions to modify or delete the file. 54 | COPY [ "./src/firefox.plus/user.js", "./.mozilla/firefox/profile0.default/" ] 55 | COPY [ "./src/firefox.plus/user.js", "./firefox.plus/user.js" ] 56 | 57 | RUN "${STARTUPDIR}"/set_user_permissions.sh "$STARTUPDIR" "$HOME" 58 | 59 | ### Switch to non-root user 60 | USER ${VNC_USER} 61 | 62 | ### Issue #7 (base): Mitigating problems with foreground mode 63 | WORKDIR ${STARTUPDIR} 64 | -------------------------------------------------------------------------------- /src/create_user_and_fix_permissions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## Creates an ordinary non-root VNC_USER and calls the script to fix the file permissions 3 | 4 | ### every exit != 0 fails the script 5 | set -e 6 | set -u 7 | 8 | UNAME=0 9 | UGROUP=0 10 | 11 | if [[ -n "${VNC_USER}" ]] ; then 12 | case "$VNC_USER" in 13 | root|0) UNAME=root; UGROUP=$UNAME;; # exact match 14 | root:*|0:*) UNAME=root; UGROUP=$UNAME;; # match from the beginning 15 | *:root|*:0) UNAME=root; UGROUP=$UNAME;; # match at the end 16 | *) UNAME=${VNC_USER/%:*/}; UGROUP=${VNC_USER/#*:/};; # else case 17 | esac 18 | 19 | if [[ "$UGROUP" != "" && "$UGROUP" != "root" ]] ; then 20 | 21 | ### Creates the group only if it does not exist yet 22 | echo "Creating group $UGROUP if needed" 23 | groupadd -f $UGROUP 24 | 25 | ### Returns "0" if the user exists, or "1" otherwise 26 | missing_user=$(id -u $UNAME > /dev/null 2>&1; echo $?) 27 | 28 | if [[ $missing_user != 0 ]] ; then 29 | echo "Creating non-root user \"$VNC_USER\"." 30 | useradd --no-log-init --gid $UGROUP --home-dir $HOME --shell /bin/bash --password $VNC_PW $UNAME 31 | fi 32 | else 33 | echo "Will not create root user \"$VNC_USER\"." 34 | fi 35 | fi 36 | 37 | FIXING="Fixing permissions: " 38 | 39 | for var in "$@" 40 | do 41 | echo "$FIXING $var" 42 | find "$var"/ -name '*.sh' -exec chmod a+x {} + 43 | find "$var"/ -name '*.desktop' -exec chmod a+x {} + 44 | 45 | ### folder and its content belong to the group zero (recursively) 46 | chgrp -R 0 "$var" && chmod -R -v a+rw "$var" && find "$var" -type d -exec chmod -v a+x {} + 47 | done 48 | 49 | MOZILLA="$HOME/.mozilla" 50 | FFOX="$MOZILLA/firefox" 51 | FFOX_BAK="$HOME/firefox.plus" 52 | if [[ -d "$MOZILLA" ]] ; then 53 | 54 | LIST="$MOZILLA $FFOX $FFOX/profile0.default $FFOX_BAK" 55 | for var in $LIST 56 | do 57 | if [[ -d "$var" ]] ; then 58 | echo "$FIXING $var" 59 | chown -R $UNAME:$UGROUP $var 60 | chmod -R 700 $var 61 | fi 62 | done 63 | 64 | ### careful, number of elements in both arrays should be the same 65 | ARRA=("$FFOX/profiles.ini" "$FFOX/profile0.default/user.js" "$FFOX_BAK/user.js") 66 | ARRB=(644 600 600) 67 | MAXI=${#ARRA[@]} 68 | for (( i=0; i<$MAXI; i++ )) 69 | do 70 | if [[ -f ${ARRA[$i]} ]] ; then 71 | echo "$FIXING ${ARRA[$i]}" 72 | chmod "${ARRB[$i]}" "${ARRA[$i]}" 73 | fi 74 | done 75 | fi 76 | -------------------------------------------------------------------------------- /local-building-example.md: -------------------------------------------------------------------------------- 1 | # Local building example 2 | 3 | - [Local building example](#local-building-example) 4 | - [Preparation](#preparation) 5 | - [Building pipeline](#building-pipeline) 6 | - [Step 1: `build`](#step-1-build) 7 | - [Step 2: `test`](#step-2-test) 8 | - [Step 3: `push`](#step-3-push) 9 | - [All steps at once](#all-steps-at-once) 10 | 11 | Docker Hub has removed auto-building from free plans since 2021-07-26. 12 | 13 | This page describes how to build the image locally and optionally push it to Docker Hub. 14 | 15 | If you just want to build the image locally without publishing it on Docker Hub, then you can use the `one-liners` shown at the top of the Dockerfile. 16 | 17 | There is a helper utility `builder.sh`, which supports executing the whole building pipeline locally, including pushing the image to Docker Hub. 18 | 19 | ## Preparation 20 | 21 | Open a terminal windows and change the current directory to the root of the project (where the license file is). 22 | 23 | There is an example secrets file in the `utils` subdirectory of the project. Copy and modify it and then source it in the terminal: 24 | 25 | ```bash 26 | ### make a copy and then modify it 27 | cp utils/example-secrets.rc secrets.rc 28 | 29 | ### source the secrets 30 | source ./secrets.rc 31 | ``` 32 | 33 | ## Building pipeline 34 | 35 | The full building pipeline consists of the following four hook scripts and one utility script: 36 | 37 | - `build` 38 | - `test` 39 | - `push` 40 | - `util-refresh-readme.sh` 41 | 42 | The order of executing the scripts is important. 43 | 44 | The commands in the following example would build and publish the image `accetto/ubuntu-vnc-xfce-firefox-plus:latest`. 45 | 46 | The helper utility `builder.sh` will be used. Alternatively you can also use the hook scripts directly. 47 | 48 | ### Step 1: `build` 49 | 50 | ```bash 51 | ./builder.sh latest build 52 | ``` 53 | 54 | This command builds a new local image. 55 | 56 | ### Step 2: `test` 57 | 58 | ```bash 59 | ./builder.sh latest test 60 | ``` 61 | 62 | This command checks if the version sticker has changed. This step is optional and you can skip it if you are not interested in the version sticker value. 63 | 64 | Otherwise, if the version sticker has changed since the last project update, then adjust the version sticker variables in the `env` hook script and repeat the steps 1 and 2. 65 | 66 | Also update the `README` file using the helper utility `util-refresh-readme.sh`. 67 | 68 | ### Step 3: `push` 69 | 70 | ```bash 71 | ./builder.sh latest push 72 | ``` 73 | 74 | This command will push the new image to Docker Hub. 75 | 76 | Note that currently you have to update the `README` file on Docker Hub yourself. You can do it in edit mode by simple copy-and-paste from the local file, which you've already updated by the helper utility described above. 77 | 78 | ### All steps at once 79 | 80 | Alternatively you can execute the whole building pipeline using the `all` command: 81 | 82 | ```bash 83 | ./builder.sh latest all 84 | ``` 85 | 86 | Note that this command doesn't update the `README` file. You still have to do it yourself using the helper utility described above. 87 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # ./hooks/build latest 2 | # ./hooks/test latest 3 | 4 | ### Example: Build and test 'dev' tag locally like 5 | ### ./hooks/build dev 6 | ### ./hooks/test dev 7 | ### or with additional arguments 8 | ### ./hooks/build dev --no-cache 9 | ### ./hooks/test dev 10 | ### or using the utility 11 | ### ./utils/util-hdx.sh Dockerfile 3 12 | ### ./utils/util-hdx.sh Dockerfile 4 13 | ### The last output line should be '+ exit 0' 14 | ### If '+ exit 1' then adjust the version sticker 15 | ### variables in script './hooks/env' 16 | 17 | ARG BASETAG=latest 18 | 19 | FROM accetto/ubuntu-vnc-xfce:${BASETAG} as stage-install 20 | 21 | ### Be sure to use root user 22 | USER 0 23 | 24 | ### 'apt-get clean' runs automatically 25 | RUN apt-get update \ 26 | && DEBIAN_FRONTEND=noninteractive apt-get install -y \ 27 | firefox \ 28 | && rm -rf /var/lib/apt/lists/* 29 | 30 | ### Alternatively install an explicit Firefox version 31 | ### http://releases.mozilla.org/pub/firefox/releases/67.0.4/linux-x86_64/en-US/firefox-67.0.4.tar.bz2 32 | # RUN \ 33 | # FIREFOX_VERSION=67.0.4 \ 34 | # FIREFOX_DISTRO=linux-x86_64 \ 35 | # FIREFOX_PATH=/usr/lib/firefox \ 36 | # && mkdir -p ${FIREFOX_PATH} \ 37 | # && wget -qO- http://releases.mozilla.org/pub/firefox/releases/${FIREFOX_VERSION}/${FIREFOX_DISTRO}/en-US/firefox-${FIREFOX_VERSION}.tar.bz2 \ 38 | # | tar xvj -C /usr/lib/ \ 39 | # && ln -s ${FIREFOX_PATH}/firefox /usr/bin/firefox 40 | 41 | FROM stage-install as stage-config 42 | 43 | ### Arguments can be provided during build 44 | ARG ARG_VNC_USER 45 | 46 | ENV VNC_USER=${ARG_VNC_USER:-headless:headless} 47 | 48 | WORKDIR ${HOME} 49 | SHELL ["/bin/bash", "-c"] 50 | 51 | ### Create the default profile folder and put the file with default preferences there. 52 | ### The preferences will be forced for each session, but only in the profile containing the file. 53 | ### The VNC user ('headles:headless' by default) will get permissions to modify or delete the file. 54 | ### There will be also a backup copy of the proto-profile. 55 | RUN mkdir \ 56 | ./.mozilla \ 57 | ./.mozilla/firefox \ 58 | ./.mozilla/firefox/profile0.default \ 59 | ./firefox.plus 60 | 61 | COPY [ "./src/firefox/profiles.ini", "./.mozilla/firefox/" ] 62 | COPY [ "./src/firefox.plus/user.js", "./.mozilla/firefox/profile0.default/" ] 63 | COPY [ "./src/create_user_and_fix_permissions.sh", "./src/patch_vnc_startup.*", "./" ] 64 | COPY [ "./src/firefox.plus/*.js", "./src/firefox.plus/*.sh", "./firefox.plus/"] 65 | COPY [ "./src/firefox.plus/*.svg", "/usr/share/icons/hicolor/scalable/apps/"] 66 | 67 | ### 'sync' mitigates automated build failures 68 | RUN \ 69 | chmod +x \ 70 | ./create_user_and_fix_permissions.sh \ 71 | ./patch_vnc_startup.sh \ 72 | ./firefox.plus/*.sh \ 73 | && sync \ 74 | && ./patch_vnc_startup.sh \ 75 | && ./create_user_and_fix_permissions.sh $STARTUPDIR $HOME \ 76 | && rm \ 77 | ./*.sh \ 78 | ./patch_vnc_startup.txt \ 79 | && gtk-update-icon-cache -f /usr/share/icons/hicolor 80 | 81 | FROM stage-config as stage-final 82 | 83 | ### Arguments can be provided during build 84 | ARG ARG_REFRESHED_AT 85 | ARG ARG_VCS_REF 86 | ARG ARG_VERSION_STICKER 87 | ARG ARG_VNC_BLACKLIST_THRESHOLD 88 | ARG ARG_VNC_BLACKLIST_TIMEOUT 89 | ARG ARG_VNC_RESOLUTION 90 | 91 | LABEL \ 92 | any.accetto.description="Headless Ubuntu VNC/noVNC container with Xfce desktop and customizable Firefox" \ 93 | any.accetto.display-name="Headless Ubuntu/Xfce VNC/noVNC container with customizable Firefox" \ 94 | any.accetto.tags="ubuntu, xfce, vnc, novnc, firefox" \ 95 | version-sticker="${ARG_VERSION_STICKER}" \ 96 | org.label-schema.vcs-ref="${ARG_VCS_REF}" \ 97 | org.label-schema.vcs-url="https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus" 98 | 99 | ENV \ 100 | REFRESHED_AT=${ARG_REFRESHED_AT} \ 101 | VERSION_STICKER=${ARG_VERSION_STICKER} \ 102 | VNC_BLACKLIST_THRESHOLD=${ARG_VNC_BLACKLIST_THRESHOLD:-20} \ 103 | VNC_BLACKLIST_TIMEOUT=${ARG_VNC_BLACKLIST_TIMEOUT:-0} \ 104 | VNC_RESOLUTION=${ARG_VNC_RESOLUTION:-1360x768} 105 | 106 | ### Preconfigure Xfce 107 | COPY [ "./src/home/Desktop", "./Desktop/" ] 108 | COPY [ "./src/home/config/xfce4/panel", "./.config/xfce4/panel/" ] 109 | COPY [ "./src/home/config/xfce4/xfconf/xfce-perchannel-xml", "./.config/xfce4/xfconf/xfce-perchannel-xml/" ] 110 | COPY [ "./src/startup/version_sticker.sh", "${STARTUPDIR}/" ] 111 | 112 | ### Fix permissions 113 | RUN \ 114 | chmod a+wx "${STARTUPDIR}"/version_sticker.sh \ 115 | && "${STARTUPDIR}"/set_user_permissions.sh "${STARTUPDIR}" "${HOME}" 116 | 117 | ### Switch to non-root user 118 | USER ${VNC_USER} 119 | 120 | ### Issue #7 (base): Mitigating problems with foreground mode 121 | WORKDIR ${STARTUPDIR} 122 | -------------------------------------------------------------------------------- /src/home/config/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /src/firefox.plus/copy_firefox_user_preferences.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ### @accetto (https://github.com/accetto) (https://hub.docker.com/u/accetto/) 3 | 4 | # ARG_OPTIONAL_SINGLE([source],[s],[Source folder (where 'user.js' is).],[/home/headless/firefox.plus]) 5 | # ARG_OPTIONAL_SINGLE([target],[t],[Target folder (where Firefox profiles are).],[/home/headless/.mozilla/firefox]) 6 | # ARG_VERSION([echo $0 v19.06.08]) 7 | # ARG_HELP([Copy 'user.js' into existing Firefox profiles]) 8 | # ARGBASH_GO() 9 | # needed because of Argbash --> m4_ignore([ 10 | ### START OF CODE GENERATED BY Argbash v2.8.0 one line above ### 11 | # Argbash is a bash code generator used to get arguments parsing right. 12 | # Argbash is FREE SOFTWARE, see https://argbash.io for more info 13 | 14 | 15 | die() 16 | { 17 | local _ret=$2 18 | test -n "$_ret" || _ret=1 19 | test "$_PRINT_HELP" = yes && print_help >&2 20 | echo "$1" >&2 21 | exit ${_ret} 22 | } 23 | 24 | 25 | begins_with_short_option() 26 | { 27 | local first_option all_short_options='stvh' 28 | first_option="${1:0:1}" 29 | test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0 30 | } 31 | 32 | # THE DEFAULTS INITIALIZATION - OPTIONALS 33 | _arg_source="/home/headless/firefox.plus" 34 | _arg_target="/home/headless/.mozilla/firefox" 35 | 36 | 37 | print_help() 38 | { 39 | printf '%s\n' "Copy 'user.js' into existing Firefox profiles" 40 | printf 'Usage: %s [-s|--source ] [-t|--target ] [-v|--version] [-h|--help]\n' "$0" 41 | printf '\t%s\n' "-s, --source: Source folder (where 'user.js' is). (default: '/home/headless/firefox.plus')" 42 | printf '\t%s\n' "-t, --target: Target folder (where Firefox profiles are). (default: '/home/headless/.mozilla/firefox')" 43 | printf '\t%s\n' "-v, --version: Prints version" 44 | printf '\t%s\n' "-h, --help: Prints help" 45 | } 46 | 47 | 48 | parse_commandline() 49 | { 50 | while test $# -gt 0 51 | do 52 | _key="$1" 53 | case "$_key" in 54 | -s|--source) 55 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 56 | _arg_source="$2" 57 | shift 58 | ;; 59 | --source=*) 60 | _arg_source="${_key##--source=}" 61 | ;; 62 | -s*) 63 | _arg_source="${_key##-s}" 64 | ;; 65 | -t|--target) 66 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 67 | _arg_target="$2" 68 | shift 69 | ;; 70 | --target=*) 71 | _arg_target="${_key##--target=}" 72 | ;; 73 | -t*) 74 | _arg_target="${_key##-t}" 75 | ;; 76 | -v|--version) 77 | echo $0 v19.06.08 78 | exit 0 79 | ;; 80 | -v*) 81 | echo $0 v19.06.08 82 | exit 0 83 | ;; 84 | -h|--help) 85 | print_help 86 | exit 0 87 | ;; 88 | -h*) 89 | print_help 90 | exit 0 91 | ;; 92 | *) 93 | _PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1 94 | ;; 95 | esac 96 | shift 97 | done 98 | } 99 | 100 | parse_commandline "$@" 101 | 102 | # OTHER STUFF GENERATED BY Argbash 103 | 104 | ### END OF CODE GENERATED BY Argbash (sortof) ### ]) 105 | # [ <-- needed because of Argbash 106 | 107 | _counter=0 108 | _file_userjs="user.js" 109 | _file_profilesini="profiles.ini" 110 | _full_userjs="" 111 | _full_profilesini="" 112 | _input="" 113 | _line=0 114 | _mark="" 115 | _oldIFS="" 116 | declare -a _list 117 | 118 | # DEBUG=true 119 | 120 | [[ $DEBUG ]] && _arg_source="." 121 | [[ $DEBUG ]] && _arg_target="../.mozilla/firefox" 122 | 123 | fn_die() 124 | { 125 | local _ret=$2 126 | test -n "$_ret" || _ret=1 127 | test "$_PRINT_HELP" = yes && print_help >&2 128 | echo "$1" >&2 129 | read -rp $"Press any key to close this window ... " -n1 _input 130 | exit ${_ret} 131 | } 132 | 133 | ### source and target folders must be provided 134 | # : ${_arg_source?} ${_arg_target?} 135 | [[ ! ${_arg_source} ]] && fn_die "Source path must be provided!" 136 | [[ ! ${_arg_target} ]] && fn_die "Target path must be provided!" 137 | 138 | _full_userjs="${_arg_source}/${_file_userjs}" 139 | _full_profilesini="${_arg_target}/${_file_profilesini}" 140 | 141 | ### source folder must contain 'user.js' 142 | [[ -f "${_full_userjs}" ]] && echo "File '${_full_userjs}' exists." || fn_die "FAILED: File '${_full_userjs}' not found!" 143 | 144 | ### target folder must contain 'profiles.ini' 145 | [[ -f ${_full_profilesini} ]] && echo "File '${_full_profilesini}' exists." || fn_die "FAILED: File '${_full_profilesini}' not found!" 146 | 147 | ### only profiles in 'profiles.ini' will be processed, get their count 148 | _counter=$( grep -c -E '^Path=' "${_full_profilesini}" ) 149 | 150 | if [[ $_counter -gt 0 ]] ; then 151 | 152 | ### extract profile folder names from 'profiles.ini' into the array 153 | ### be aware that user profile names/folders can contain spaces 154 | _oldIFS=$IFS 155 | IFS=$'\x0A'$'\x0D' 156 | _list=( $( grep -E '^Path=' "${_full_profilesini}" | sed -E -e 's/^Path=//' ) ) 157 | IFS=$_oldIFS 158 | 159 | echo "Following profiles found in '${_file_profilesini}' ('+|-' means with/without '${_file_userjs}'):" 160 | _counter=0 161 | for p in "${_list[@]}" ; do 162 | _counter=$((${_counter}+1)) 163 | [[ $(ls "${_arg_target}/$p/${_file_userjs}" 2>/dev/null) ]] && _mark=" + " || _mark=" - " 164 | printf ' %s %s %s\n' "$_counter" "$_mark" "$p" 165 | done 166 | 167 | ### user interaction 168 | read -rp $"Into which profile to copy '${_file_userjs}' (line number or 'all')? " _input 169 | _input=$(echo ${_input,,} | grep -i -E "^[0-9]+$|^all$") 170 | [[ ! ${_input} ]] && fn_die "INTERRUPTED: Line number or 'all' required!" 171 | if [[ "${_input,,}" != "all" ]] ; then 172 | 173 | ### line number has been provided 174 | _line=${_input} 175 | [[ ${_line} -lt 1 || ${_line} -gt ${_counter} ]] && fn_die "FAILED: Line number must be from the interval [1..${_counter}]!" 176 | _line=$((${_line}-1)) 177 | 178 | ### copy 'user.js' into the selected profile folder 179 | cp -v "${_full_userjs}" "${_arg_target}/${_list[${_line}]}/" 180 | 181 | else 182 | # 'all' has been provided 183 | ### copy 'user.js' into all profiles not containing it yet 184 | for p in "${_list[@]}" ; do 185 | cp -v "${_full_userjs}" "${_arg_target}/$p/" 186 | done 187 | fi 188 | 189 | fn_die "SUCCESS." 0 190 | else 191 | echo "No profiles found in '${_full_profilesini}'." 192 | fi 193 | 194 | fn_die "" 0 195 | 196 | # ] <-- needed because of Argbash 197 | -------------------------------------------------------------------------------- /src/firefox.plus/accetto.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 23 | 25 | image/svg+xml 26 | 28 | 29 | 30 | 31 | 32 | 34 | 54 | 116 | 117 | -------------------------------------------------------------------------------- /utils/util-hdx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ### @accetto (https://github.com/accetto) (https://hub.docker.com/u/accetto/) 3 | 4 | # ARG_POSITIONAL_INF([args],[Command arguments will be used as follows:\n \ 5 | # args[0] - The file containing the line to be execute (required) \n \ 6 | # args[1] - The number of the line to be executed (required) \n \ 7 | # args[2] and above will be inserted after 'docker build', if found, or appended otherwise \n \ 8 | #]) 9 | # ARG_POSITIONAL_DOUBLEDASH([]) 10 | # ARG_OPTIONAL_SINGLE([lines],[],[Number of header lines to display],[10]) 11 | # ARG_OPTIONAL_BOOLEAN([echo],[],[Just print the command line to be executed]) 12 | # ARG_VERSION([echo $0 v20.10.04]) 13 | # ARG_HELP([Displays the file head and executes the chosen line, removing the first occurrence of '#' and trimming it from the left first.\nProviding the line number argument skips the interaction and executes the given line directly.]) 14 | # ARGBASH_SET_INDENT([ ]) 15 | # ARGBASH_GO() 16 | # needed because of Argbash --> m4_ignore([ 17 | ### START OF CODE GENERATED BY Argbash v2.8.1 one line above ### 18 | # Argbash is a bash code generator used to get arguments parsing right. 19 | # Argbash is FREE SOFTWARE, see https://argbash.io for more info 20 | 21 | 22 | die() 23 | { 24 | local _ret="${2:-1}" 25 | test "${_PRINT_HELP:-no}" = yes && print_help >&2 26 | echo "$1" >&2 27 | exit "${_ret}" 28 | } 29 | 30 | 31 | begins_with_short_option() 32 | { 33 | local first_option all_short_options='vh' 34 | first_option="${1:0:1}" 35 | test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0 36 | } 37 | 38 | # THE DEFAULTS INITIALIZATION - POSITIONALS 39 | _positionals=() 40 | _arg_args=() 41 | # THE DEFAULTS INITIALIZATION - OPTIONALS 42 | _arg_lines="10" 43 | _arg_echo="off" 44 | 45 | 46 | print_help() 47 | { 48 | printf '%s\n' "Displays the file head and executes the chosen line, removing the first occurrence of '#' and trimming it from the left first. 49 | Providing the line number argument skips the interaction and executes the given line directly." 50 | printf 'Usage: %s [--lines ] [--(no-)echo] [-v|--version] [-h|--help] [--] [] ... [] ...\n' "$0" 51 | printf '\t%s\n' ": Command arguments will be used as follows: 52 | \ 53 | # args[0] - The file containing the line to be execute (required) 54 | \ 55 | # args[1] - The number of the line to be executed (required) 56 | \ 57 | # args[2] and above will be inserted after 'docker build', if found, or appended otherwise 58 | \ 59 | #" 60 | printf '\t%s\n' "--lines: Number of header lines to display (default: '10')" 61 | printf '\t%s\n' "--echo, --no-echo: Just print the command line to be executed (off by default)" 62 | printf '\t%s\n' "-v, --version: Prints version" 63 | printf '\t%s\n' "-h, --help: Prints help" 64 | } 65 | 66 | 67 | parse_commandline() 68 | { 69 | _positionals_count=0 70 | while test $# -gt 0 71 | do 72 | _key="$1" 73 | if test "$_key" = '--' 74 | then 75 | shift 76 | test $# -gt 0 || break 77 | _positionals+=("$@") 78 | _positionals_count=$((_positionals_count + $#)) 79 | shift $(($# - 1)) 80 | _last_positional="$1" 81 | break 82 | fi 83 | case "$_key" in 84 | --lines) 85 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 86 | _arg_lines="$2" 87 | shift 88 | ;; 89 | --lines=*) 90 | _arg_lines="${_key##--lines=}" 91 | ;; 92 | --no-echo|--echo) 93 | _arg_echo="on" 94 | test "${1:0:5}" = "--no-" && _arg_echo="off" 95 | ;; 96 | -v|--version) 97 | echo $0 v20.10.04 98 | exit 0 99 | ;; 100 | -v*) 101 | echo $0 v20.10.04 102 | exit 0 103 | ;; 104 | -h|--help) 105 | print_help 106 | exit 0 107 | ;; 108 | -h*) 109 | print_help 110 | exit 0 111 | ;; 112 | *) 113 | _last_positional="$1" 114 | _positionals+=("$_last_positional") 115 | _positionals_count=$((_positionals_count + 1)) 116 | ;; 117 | esac 118 | shift 119 | done 120 | } 121 | 122 | 123 | assign_positional_args() 124 | { 125 | local _positional_name _shift_for=$1 126 | _positional_names="" 127 | _our_args=$((${#_positionals[@]} - 0)) 128 | for ((ii = 0; ii < _our_args; ii++)) 129 | do 130 | _positional_names="$_positional_names _arg_args[$((ii + 0))]" 131 | done 132 | 133 | shift "$_shift_for" 134 | for _positional_name in ${_positional_names} 135 | do 136 | test $# -gt 0 || break 137 | eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1 138 | shift 139 | done 140 | } 141 | 142 | parse_commandline "$@" 143 | assign_positional_args 1 "${_positionals[@]}" 144 | 145 | # OTHER STUFF GENERATED BY Argbash 146 | 147 | ### END OF CODE GENERATED BY Argbash (sortof) ### ]) 148 | # [ <-- needed because of Argbash 149 | 150 | ### ######################### 151 | ### CUSTOM CODE BEGEINGS HERE 152 | ### ######################### 153 | 154 | main() { 155 | local _cmd="" 156 | local _file="" 157 | local _input="" 158 | local _leftovers="" 159 | local _key='' 160 | local -i _line=0 161 | local -i _size=10 162 | 163 | [[ ${#_arg_args[@]} -lt 2 ]] && die "FAILED: First two arguments are mandatory!" 164 | 165 | _file="${_arg_args[0]}" 166 | 167 | _line=${_arg_args[1]} 168 | [[ ${_line} -le 0 ]] && _line=0 169 | 170 | [[ ! -f "${_file}" ]] && die "FAILED: File \"${_file}\" not found!" 171 | 172 | [[ ${#_arg_args[@]} -gt 2 ]] && _leftovers="${_arg_args[@]:2}" 173 | 174 | _size=$(wc -l <"${_file}") 175 | [[ ${_size} -gt ${_arg_lines} ]] && _size=${_arg_lines} 176 | 177 | if [[ ${_line} -le 0 ]]; then 178 | ### output the header numbering the lines 179 | head -n ${_size} "${_file}" | cat -n 180 | 181 | ### get the line number 182 | read -rp $'Which line to execute? ' _input 183 | _input=$(echo ${_input} | grep -E "^[0-9]+$") 184 | [[ ${_input} ]] && _line=${_input} || die "INTERRUPTED: Numeric input required!" 185 | [[ ${_line} -lt 1 || ${_line} -gt ${_size} ]] && die "FAILED: The line number must be from the interval [1..${_size}]!" 186 | fi 187 | 188 | ### get the command line, remove the first '#' and trim it from the left 189 | _cmd=$(sed "${_line}q;d" "${_file}") 190 | _cmd=$(echo "${_cmd}" | sed -r -e 's/^\s*#\s*//g') 191 | 192 | ### add the leftover arguments to the command line 193 | if [[ -n "${_leftovers}" ]] ; then 194 | if [[ "${_cmd}" =~ 'docker build' ]] ; then 195 | ### insert the leftovers after 'docker build' 196 | _cmd=$(echo "${_cmd}" | sed -r -e "s/docker build/docker build ${_leftovers}/g" ) 197 | else 198 | ### just append the leftovers 199 | _cmd="${_cmd} ${_arg_args[@]:2}" 200 | fi 201 | fi 202 | 203 | ### display the command to be executed 204 | echo "${_cmd}" 205 | 206 | if [[ ${_line} -eq 0 && "${_arg_echo}" = "off" ]]; then 207 | ### ask for user confirmation 208 | read -rp $'Execute the line above? (y) ' -n1 _key 209 | echo 210 | # [[ "${_key,,}" != "y" ]] && die "INTERRUPTED" ## not working on qnas 211 | [[ "${_key}" != "y" ]] && die "INTERRUPTED" 212 | fi 213 | 214 | if [[ "${_arg_echo}" == "off" ]]; then 215 | eval "${_cmd}" 216 | fi 217 | } 218 | 219 | main $@ 220 | 221 | # ] <-- needed because of Argbash 222 | -------------------------------------------------------------------------------- /src/home/Desktop/firefox.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Name=Firefox Web Browser 4 | Name[ar]=متصفح الويب فَيَرفُكْس 5 | Name[ast]=Restolador web Firefox 6 | Name[bn]=ফায়ারফক্স ওয়েব ব্রাউজার 7 | Name[ca]=Navegador web Firefox 8 | Name[cs]=Firefox Webový prohlížeč 9 | Name[da]=Firefox - internetbrowser 10 | Name[el]=Περιηγητής Firefox 11 | Name[es]=Navegador web Firefox 12 | Name[et]=Firefoxi veebibrauser 13 | Name[fa]=مرورگر اینترنتی Firefox 14 | Name[fi]=Firefox-selain 15 | Name[fr]=Navigateur Web Firefox 16 | Name[gl]=Navegador web Firefox 17 | Name[he]=דפדפן האינטרנט Firefox 18 | Name[hr]=Firefox web preglednik 19 | Name[hu]=Firefox webböngésző 20 | Name[it]=Firefox Browser Web 21 | Name[ja]=Firefox ウェブ・ブラウザ 22 | Name[ko]=Firefox 웹 브라우저 23 | Name[ku]=Geroka torê Firefox 24 | Name[lt]=Firefox interneto naršyklė 25 | Name[nb]=Firefox Nettleser 26 | Name[nl]=Firefox webbrowser 27 | Name[nn]=Firefox Nettlesar 28 | Name[no]=Firefox Nettleser 29 | Name[pl]=Przeglądarka WWW Firefox 30 | Name[pt]=Firefox Navegador Web 31 | Name[pt_BR]=Navegador Web Firefox 32 | Name[ro]=Firefox – Navigator Internet 33 | Name[ru]=Веб-браузер Firefox 34 | Name[sk]=Firefox - internetový prehliadač 35 | Name[sl]=Firefox spletni brskalnik 36 | Name[sv]=Firefox webbläsare 37 | Name[tr]=Firefox Web Tarayıcısı 38 | Name[ug]=Firefox توركۆرگۈ 39 | Name[uk]=Веб-браузер Firefox 40 | Name[vi]=Trình duyệt web Firefox 41 | Name[zh_CN]=Firefox 网络浏览器 42 | Name[zh_TW]=Firefox 網路瀏覽器 43 | Comment=Browse the World Wide Web 44 | Comment[ar]=تصفح الشبكة العنكبوتية العالمية 45 | Comment[ast]=Restola pela Rede 46 | Comment[bn]=ইন্টারনেট ব্রাউজ করুন 47 | Comment[ca]=Navegueu per la web 48 | Comment[cs]=Prohlížení stránek World Wide Webu 49 | Comment[da]=Surf på internettet 50 | Comment[de]=Im Internet surfen 51 | Comment[el]=Μπορείτε να περιηγηθείτε στο διαδίκτυο (Web) 52 | Comment[es]=Navegue por la web 53 | Comment[et]=Lehitse veebi 54 | Comment[fa]=صفحات شبکه جهانی اینترنت را مرور نمایید 55 | Comment[fi]=Selaa Internetin WWW-sivuja 56 | Comment[fr]=Naviguer sur le Web 57 | Comment[gl]=Navegar pola rede 58 | Comment[he]=גלישה ברחבי האינטרנט 59 | Comment[hr]=Pretražite web 60 | Comment[hu]=A világháló böngészése 61 | Comment[it]=Esplora il web 62 | Comment[ja]=ウェブを閲覧します 63 | Comment[ko]=웹을 돌아 다닙니다 64 | Comment[ku]=Li torê bigere 65 | Comment[lt]=Naršykite internete 66 | Comment[nb]=Surf på nettet 67 | Comment[nl]=Verken het internet 68 | Comment[nn]=Surf på nettet 69 | Comment[no]=Surf på nettet 70 | Comment[pl]=Przeglądanie stron WWW 71 | Comment[pt]=Navegue na Internet 72 | Comment[pt_BR]=Navegue na Internet 73 | Comment[ro]=Navigați pe Internet 74 | Comment[ru]=Доступ в Интернет 75 | Comment[sk]=Prehliadanie internetu 76 | Comment[sl]=Brskajte po spletu 77 | Comment[sv]=Surfa på webben 78 | Comment[tr]=İnternet'te Gezinin 79 | Comment[ug]=دۇنيادىكى توربەتلەرنى كۆرگىلى بولىدۇ 80 | Comment[uk]=Перегляд сторінок Інтернету 81 | Comment[vi]=Để duyệt các trang web 82 | Comment[zh_CN]=浏览互联网 83 | Comment[zh_TW]=瀏覽網際網路 84 | GenericName=Web Browser 85 | GenericName[ar]=متصفح ويب 86 | GenericName[ast]=Restolador Web 87 | GenericName[bn]=ওয়েব ব্রাউজার 88 | GenericName[ca]=Navegador web 89 | GenericName[cs]=Webový prohlížeč 90 | GenericName[da]=Webbrowser 91 | GenericName[el]=Περιηγητής διαδικτύου 92 | GenericName[es]=Navegador web 93 | GenericName[et]=Veebibrauser 94 | GenericName[fa]=مرورگر اینترنتی 95 | GenericName[fi]=WWW-selain 96 | GenericName[fr]=Navigateur Web 97 | GenericName[gl]=Navegador Web 98 | GenericName[he]=דפדפן אינטרנט 99 | GenericName[hr]=Web preglednik 100 | GenericName[hu]=Webböngésző 101 | GenericName[it]=Browser web 102 | GenericName[ja]=ウェブ・ブラウザ 103 | GenericName[ko]=웹 브라우저 104 | GenericName[ku]=Geroka torê 105 | GenericName[lt]=Interneto naršyklė 106 | GenericName[nb]=Nettleser 107 | GenericName[nl]=Webbrowser 108 | GenericName[nn]=Nettlesar 109 | GenericName[no]=Nettleser 110 | GenericName[pl]=Przeglądarka WWW 111 | GenericName[pt]=Navegador Web 112 | GenericName[pt_BR]=Navegador Web 113 | GenericName[ro]=Navigator Internet 114 | GenericName[ru]=Веб-браузер 115 | GenericName[sk]=Internetový prehliadač 116 | GenericName[sl]=Spletni brskalnik 117 | GenericName[sv]=Webbläsare 118 | GenericName[tr]=Web Tarayıcı 119 | GenericName[ug]=توركۆرگۈ 120 | GenericName[uk]=Веб-браузер 121 | GenericName[vi]=Trình duyệt Web 122 | GenericName[zh_CN]=网络浏览器 123 | GenericName[zh_TW]=網路瀏覽器 124 | Keywords=Internet;WWW;Browser;Web;Explorer 125 | Keywords[ar]=انترنت;إنترنت;متصفح;ويب;وب 126 | Keywords[ast]=Internet;WWW;Restolador;Web;Esplorador 127 | Keywords[ca]=Internet;WWW;Navegador;Web;Explorador;Explorer 128 | Keywords[cs]=Internet;WWW;Prohlížeč;Web;Explorer 129 | Keywords[da]=Internet;Internettet;WWW;Browser;Browse;Web;Surf;Nettet 130 | Keywords[de]=Internet;WWW;Browser;Web;Explorer;Webseite;Site;surfen;online;browsen 131 | Keywords[el]=Internet;WWW;Browser;Web;Explorer;Διαδίκτυο;Περιηγητής;Firefox;Φιρεφοχ;Ιντερνετ 132 | Keywords[es]=Explorador;Internet;WWW 133 | Keywords[fi]=Internet;WWW;Browser;Web;Explorer;selain;Internet-selain;internetselain;verkkoselain;netti;surffaa 134 | Keywords[fr]=Internet;WWW;Browser;Web;Explorer;Fureteur;Surfer;Navigateur 135 | Keywords[he]=דפדפן;אינטרנט;רשת;אתרים;אתר;פיירפוקס;מוזילה; 136 | Keywords[hr]=Internet;WWW;preglednik;Web 137 | Keywords[hu]=Internet;WWW;Böngésző;Web;Háló;Net;Explorer 138 | Keywords[it]=Internet;WWW;Browser;Web;Navigatore 139 | Keywords[is]=Internet;WWW;Vafri;Vefur;Netvafri;Flakk 140 | Keywords[ja]=Internet;WWW;Web;インターネット;ブラウザ;ウェブ;エクスプローラ 141 | Keywords[nb]=Internett;WWW;Nettleser;Explorer;Web;Browser;Nettside 142 | Keywords[nl]=Internet;WWW;Browser;Web;Explorer;Verkenner;Website;Surfen;Online 143 | Keywords[pt]=Internet;WWW;Browser;Web;Explorador;Navegador 144 | Keywords[pt_BR]=Internet;WWW;Browser;Web;Explorador;Navegador 145 | Keywords[ru]=Internet;WWW;Browser;Web;Explorer;интернет;браузер;веб;файрфокс;огнелис 146 | Keywords[sk]=Internet;WWW;Prehliadač;Web;Explorer 147 | Keywords[sl]=Internet;WWW;Browser;Web;Explorer;Brskalnik;Splet 148 | Keywords[tr]=İnternet;WWW;Tarayıcı;Web;Gezgin;Web sitesi;Site;sörf;çevrimiçi;tara 149 | Keywords[uk]=Internet;WWW;Browser;Web;Explorer;Інтернет;мережа;переглядач;оглядач;браузер;веб;файрфокс;вогнелис;перегляд 150 | Keywords[vi]=Internet;WWW;Browser;Web;Explorer;Trình duyệt;Trang web 151 | Keywords[zh_CN]=Internet;WWW;Browser;Web;Explorer;网页;浏览;上网;火狐;Firefox;ff;互联网;网站; 152 | Keywords[zh_TW]=Internet;WWW;Browser;Web;Explorer;網際網路;網路;瀏覽器;上網;網頁;火狐 153 | Exec=firefox %u 154 | Terminal=false 155 | X-MultipleArgs=false 156 | Type=Application 157 | Icon=firefox 158 | Categories=GNOME;GTK;Network;WebBrowser; 159 | 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; 160 | StartupNotify=true 161 | Actions=NewWindow;NewPrivateWindow; 162 | 163 | [Desktop Action NewWindow] 164 | Name=Open a New Window 165 | Name[ar]=افتح نافذة جديدة 166 | Name[ast]=Abrir una ventana nueva 167 | Name[bn]=Abrir una ventana nueva 168 | Name[ca]=Obre una finestra nova 169 | Name[cs]=Otevřít nové okno 170 | Name[da]=Åbn et nyt vindue 171 | Name[de]=Ein neues Fenster öffnen 172 | Name[el]=Άνοιγμα νέου παραθύρου 173 | Name[es]=Abrir una ventana nueva 174 | Name[fi]=Avaa uusi ikkuna 175 | Name[fr]=Ouvrir une nouvelle fenêtre 176 | Name[gl]=Abrir unha nova xanela 177 | Name[he]=פתיחת חלון חדש 178 | Name[hr]=Otvori novi prozor 179 | Name[hu]=Új ablak nyitása 180 | Name[it]=Apri una nuova finestra 181 | Name[ja]=新しいウィンドウを開く 182 | Name[ko]=새 창 열기 183 | Name[ku]=Paceyeke nû veke 184 | Name[lt]=Atverti naują langą 185 | Name[nb]=Åpne et nytt vindu 186 | Name[nl]=Nieuw venster openen 187 | Name[pt]=Abrir nova janela 188 | Name[pt_BR]=Abrir nova janela 189 | Name[ro]=Deschide o fereastră nouă 190 | Name[ru]=Новое окно 191 | Name[sk]=Otvoriť nové okno 192 | Name[sl]=Odpri novo okno 193 | Name[sv]=Öppna ett nytt fönster 194 | Name[tr]=Yeni pencere aç 195 | Name[ug]=يېڭى كۆزنەك ئېچىش 196 | Name[uk]=Відкрити нове вікно 197 | Name[vi]=Mở cửa sổ mới 198 | Name[zh_CN]=新建窗口 199 | Name[zh_TW]=開啟新視窗 200 | Exec=firefox -new-window 201 | OnlyShowIn=Unity; 202 | 203 | [Desktop Action NewPrivateWindow] 204 | Name=Open a New Private Window 205 | Name[ar]=افتح نافذة جديدة للتصفح الخاص 206 | Name[ca]=Obre una finestra nova en mode d'incògnit 207 | Name[de]=Ein neues privates Fenster öffnen 208 | Name[es]=Abrir una ventana privada nueva 209 | Name[fi]=Avaa uusi yksityinen ikkuna 210 | Name[fr]=Ouvrir une nouvelle fenêtre de navigation privée 211 | Name[he]=פתיחת חלון גלישה פרטית חדש 212 | Name[hu]=Új privát ablak nyitása 213 | Name[it]=Apri una nuova finestra anonima 214 | Name[nb]=Åpne et nytt privat vindu 215 | Name[ru]=Новое приватное окно 216 | Name[sl]=Odpri novo okno zasebnega brskanja 217 | Name[tr]=Yeni bir pencere aç 218 | Name[uk]=Відкрити нове вікно у потайливому режимі 219 | Name[zh_TW]=開啟新隱私瀏覽視窗 220 | Exec=firefox -private-window 221 | OnlyShowIn=Unity; 222 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | ## accetto/ubuntu-vnc-xfce-firefox-plus 4 | 5 | [Docker Hub][this-docker] - [Git Hub][this-github] - [Wiki][this-wiki] 6 | 7 | *** 8 | 9 | ### Final release 22.11 10 | 11 | The repository has been revived and merged into the repository [ubuntu-vnc-xfce][accetto-github-ubuntu-vnc-xfce], because I've noticed, that the images are still being pulled. 12 | 13 | This original repository [ubuntu-vnc-xfce-firefox-plus][this-github] stays retired. 14 | 15 | ### Final G1v1 release 22.03.1 16 | 17 | The repository is **retired** and **archived**. It will not be developed any further and the related images on Docker Hub will not be rebuilt any more. They will phase out and they will be deleted after becoming too old. 18 | 19 | Please use the newer **third generation** (G3) repository [accetto/ubuntu-vnc-xfce-g3][accetto-ubuntu-vnc-xfce-g3] and the related images on Docker Hub instead. 20 | 21 | If you still need images based on `Ubuntu 18.04 LTS`, then feel free using the repository for building the images locally. 22 | 23 | - Updated versions: 24 | - Firefox **98.0** 25 | 26 | ### Release 22.03 27 | 28 | - Firefox **97.0.2** 29 | 30 | ### Release 22.02 31 | 32 | - Firefox **97.0** 33 | 34 | ### Release 22.01 35 | 36 | - Firefox **96.0** 37 | 38 | ### Release 21.12.1 39 | 40 | - Firefox **95.0.1** 41 | 42 | ### Release 21.12 43 | 44 | - Firefox **95.0** 45 | 46 | ### Release 21.11 47 | 48 | - Firefox **94.0** 49 | 50 | ### Release 21.10 51 | 52 | - base image has been updated to version **18.04.6** 53 | - Firefox **93.0** 54 | 55 | ### Release 21.09.1 56 | 57 | - utility `builder.sh` improved 58 | - Firefox **92.0** 59 | 60 | ### Release 21.09 61 | 62 | - Firefox **91.0.2** 63 | 64 | ### Release 21.08.1 65 | 66 | - utility `builder.sh` improved 67 | - Firefox **91.0.1** 68 | 69 | ### Release 21.08 70 | 71 | - Docker Hub has removed auto-builds from free plans since 2021-07-26, therefore 72 | - **if you stay on the free plan**, then 73 | - you can still build the images locally and then push them to Docker Hub 74 | - pushing to Docker Hub is optional 75 | - just follow the added file `local-building-example.md` 76 | - you can use the helper utility `builder.sh` 77 | - regularity of updates of images on Docker Hub cannot be guaranteed any more 78 | - Firefox **90.0.2** 79 | 80 | ### Release 21.07.1 81 | 82 | - Firefox **90.0** 83 | 84 | ### Release 21.07 85 | 86 | - Firefox **89.0.2** 87 | 88 | ### Release 21.06.1 89 | 90 | - Firefox **89.0.1** 91 | 92 | ### Release 21.06 93 | 94 | - Firefox **89.0** 95 | 96 | ### Release 21.05 97 | 98 | - Firefox **88.0.1** 99 | 100 | ### Release 21.04 101 | 102 | - TigerVNC from [Release Mirror on accetto/tigervnc][accetto-tigervnc-release-mirror] because **Bintray** is closing on 2021-05-01 (inherited from the base image) 103 | - Firefox **88.0** 104 | 105 | ### Release 21.03.1 106 | 107 | - Firefox **87.0** 108 | 109 | ### Release 21.03 110 | 111 | - Firefox **86.0** 112 | 113 | ### Release 21.02.1 114 | 115 | - Firefox **85.0.1** 116 | 117 | ### Release 21.02 118 | 119 | - Firefox **85.0** 120 | 121 | ### Release 21.01.1 122 | 123 | - Firefox **84.0.2** 124 | 125 | ### Release 21.01 126 | 127 | - Firefox **84.0.1** 128 | 129 | ### Release 20.12 130 | 131 | - README got links to the third generation (G3) of images 132 | - Firefox **84.0** 133 | 134 | ### Release 20.11 135 | 136 | - Firefox **83.0** 137 | 138 | ### Release 20.10.2 139 | 140 | - Firefox **82.0** 141 | 142 | ### Release 20.10.1 143 | 144 | - hook scripts updated 145 | - automatic archiving of previous image versions removed 146 | - switch **MOZ_FORCE_DISABLE_E10S=1** seems not working any more 147 | - build argument **ARG_MOZ_FORCE_DISABLE_E10S** removed 148 | - environment variable **MOZ_FORCE_DISABLE_E10S** removed 149 | - `singleprocess` tag removed 150 | - hook scripts updated accordingly 151 | 152 | ### Release 20.10 153 | 154 | - updated scripts (all images): 155 | - version_of.sh 156 | - version_sticker.sh 157 | - util-hdx.sh 158 | - Firefox **81.0** 159 | 160 | ### Release 20.09.1 161 | 162 | - **nano** editor added (inherited from base) 163 | 164 | ### Release 20.09 165 | 166 | - Firefox **80.0.1** 167 | 168 | ### Release 20.08.2 169 | 170 | - Firefox **80.0** 171 | 172 | ### Release 20.08.1 173 | 174 | - base image has been updated to version **18.04.5** 175 | 176 | ### Release 20.08 177 | 178 | - base image has been updated 179 | - Firefox **79.0** 180 | 181 | ### Release 20.07.1 182 | 183 | - base **ubuntu-vnc-xfce** image has been updated 184 | - Firefox **78.0.2** 185 | 186 | ### Release 20.07 187 | 188 | - Firefox **78.0.1** 189 | - fix in `push` hook script 190 | 191 | ### Release 20.06.2 192 | 193 | - Firefox **77.0.1** 194 | - **IMPORTANT**: Firefox multi-process mode is default now and therefore larger shared memory (`/dev/shm`) is required (see bellow) 195 | - environment variable **MOZ_FORCE_DISABLE_E10S** is not set by default any more 196 | - **containers with Firefox require larger shared memory** (`/dev/shm`) to run reliably 197 | - at least **256MB** is recommended (default is just 64MB) 198 | - use `docker run --shm-size=256m` 199 | - or `shm_size: 256m` at service level in docker-compose files 200 | - see [Firefox multi-process][that-wiki-firefox-multiprocess] in Wiki for description and instructions 201 | - this fixes the [issue #7 (Firefox 77.0.1 scrambles pages)](https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus/issues/7) 202 | - Internet browsing should be **sand-boxed** now 203 | - tag `singleprocess` introduced 204 | - which is single-threaded, but 205 | - please be aware that in **this** release (still Firefox **77.0.1**) webpages still will be scrambled (issue #7) 206 | - it should be fixed by Mozilla in the next Firefox release 207 | - Other changes: 208 | - default VNC resolution changed to 1360x768 209 | - added some help comments into Dockerfile 210 | - README updated 211 | 212 | ### Release 20.06.1 213 | 214 | - Quick mitigation of issue [#7 (Firefox 77.0.1 scrambles pages)](https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus/issues/7) 215 | - by rolling back **Firefox** to version **76.0.1** 216 | 217 | ### Release 20.06 218 | 219 | - Firefox **77.0.1** 220 | - minor changes in **README** 221 | - making it more similar to [accetto/xubuntu-vnc](https://hub.docker.com/r/accetto/xubuntu-vnc) and [accetto/xubuntu-vnc-novnc](https://hub.docker.com/r/accetto/xubuntu-vnc-novnc) 222 | 223 | ### Release 20.05 224 | 225 | - Firefox **76.0.1** 226 | 227 | ### Release 20.04.2 228 | 229 | - All changes inherited from the base image: 230 | - based explicitly on **ubuntu:18.04** tag 231 | - note that the tag **latest** now means **based on ubuntu:18.04** 232 | - **TigerVNC** version **1.10.1** 233 | - **websockify** updated to version **0.9.0** 234 | 235 | ### Release 20.04.1 236 | 237 | - Firefox **75.0** 238 | 239 | ### Release 20.04 240 | 241 | - Firefox **74.0.1** 242 | 243 | ### Release 20.03.1 244 | 245 | - **Ubuntu** base image updated (inherited from base) 246 | 247 | ### Release 20.03 248 | 249 | - Firefox **74.0** 250 | 251 | ### Release 20.02.3 252 | 253 | - Firefox **73.0.1** 254 | 255 | ### Release 20.02.2 256 | 257 | - **Ubuntu** base image updated to version **18.04.4** 258 | 259 | ### Release 20.02.1 260 | 261 | - Firefox **73.0** 262 | - desktop launcher for version sticker script (verbose) (inherited from the base) 263 | - container screenshot updated 264 | - **README** updated 265 | 266 | ### Release 20.02 267 | 268 | - Firefox **72.0.2** 269 | 270 | ### Release 20.01 271 | 272 | - **Ubuntu** base image has been updated 273 | - Firefox **72.0.1** 274 | 275 | ### Release 19.12.1 276 | 277 | - **Ubuntu** base image has been updated 278 | 279 | ### Release 19.12 280 | 281 | - Firefox **71.0** 282 | 283 | ### Version 19.11.2 284 | 285 | - **TigerVNC** server and client updated to version **1.10.0** (inherited from the base) 286 | 287 | ### Version 19.11.1 288 | 289 | - simplified output of `vnc_startup.sh` script (inherited from the base) 290 | - bottom panel's auto-hide behavior changed from `Intelligently` to `Always` 291 | 292 | ### Version 19.11 293 | 294 | - inherited from the base: 295 | - **ubuntu** base image updated 296 | - Firefox **70.0.1** 297 | 298 | ### Version 19.10.5 299 | 300 | - Firefox **70.0** 301 | 302 | ### Version 19.10.4 303 | 304 | - inherited from the base: 305 | - **ubuntu** base image updated 306 | - **zip**, **unzip**, **curl** and **git** added 307 | - **jq** (JSON processor) added in its latest version **1.6** 308 | - **version_of.sh** script handles also **jq** 309 | - **version_sticker.sh** reports new apps inherited from the base 310 | - `test` build hook updated 311 | - README file updated 312 | 313 | ### Version 19.10.3 314 | 315 | - README updated 316 | - **version sticker** described 317 | - new badges added 318 | - build hooks updated 319 | - command line arguments passed to `build` hook 320 | 321 | ### Version 19.10.2 322 | 323 | - badges re-designed 324 | - previous badges removed and new status badges from `badge.net` and `shields.io` introduced 325 | - `commit` badge from `microbadger.com` introduced (per tag) 326 | - `version sticker` badge introduced (as static badge from `badge.net`) 327 | - remark: it can take several hours until new badges are actually shown (caused by caching) 328 | - build hooks updated 329 | - script **util-refresh-readme.sh** introduced 330 | - Firefox updated to version **69.0.2** 331 | 332 | ### Version 19.10.1 333 | 334 | - README updated 335 | 336 | ### Version 19.10 337 | 338 | - Firefox version **69.0.1** 339 | 340 | ### Version 19.09 341 | 342 | - environment variable **VERSION_STICKER** and build argument **ARG_VERSION_STICKER** introduced 343 | - scripts **version_sticker.sh** and **version_of.sh** introduced 344 | - Firefox version **69.0** 345 | 346 | ### Version 19.08.1 347 | 348 | - newer base image (**Ubuntu 18.04.3 LTS**) (inherited from the base image) 349 | - **Firefox** updated to version **68.0.2** 350 | - environment variable **MOZ_FORCE_DISABLE_E10S** and build argument **ARG_MOZ_FORCE_DISABLE_E10S** introduced 351 | - Firefox multi-process is **disabled** by default 352 | - build argument **ARG_REFRESHED_AT** introduced 353 | - environment variable **REFRESHED_AT** set to the actual build date 354 | - utility **util-update-refreshed-at** removed 355 | 356 | ### Version 19.08 357 | 358 | - keeping Firefox on version **67.0.4** because **68.0** and **68.0.1** crash a lot (Gah. Your tab just crashed.) 359 | - installed explicitly from Mozilla distribution 360 | 361 | ### Version 19.06.4 362 | 363 | - **README** updated 364 | - reference to [accetto/xubuntu-vnc-firefox][accetto-docker-xubuntu-vnc-firefox] based on [accetto/xubuntu-vnc][accetto-docker-xubuntu-vnc] added - a streamlined and simplified image, without [noVNC][novnc] and [nss_wrapper][nsswrapper], with a growing family of derived images with various applications 365 | - Firefox version **67.0.4** 366 | 367 | ### Version 19.06.3 368 | 369 | - File manager (Thunar) pre-configured (inherited from the [base image][this-base]) 370 | - *Owner*, *Permissions* and *Group* columns shown by default 371 | - *Type* column suppressed 372 | - Fix in **create_user_and_fix_permissions.sh** 373 | - Firefox version **67.0.3** 374 | 375 | ### Version 19.06.2 376 | 377 | - Fix in **create_user_and_fix_permissions.sh** 378 | 379 | ### Version 19.06.1 380 | 381 | - Fix in **Dockerfile-plus-preferences** 382 | 383 | ### Version 19.06 384 | 385 | - Script **set_user_permissions.sh** updated (inherited from the [base image][this-base]) 386 | - root group replaced by the current user group 387 | - **TigerVNC Viewer** desktop launcher icon updated (inherited from the [base image][this-base]) 388 | - Folder **firefox.backup** renamed to **firefox.plus** 389 | - script **create_user_and_fix_permissions.sh** and related also updated 390 | - Helper utility script **copy_firefox_user_preferences.sh** added 391 | - desktop launcher **Copy FF Preferences** for the utility added 392 | - desktop launcher **FF Profile Manager** added 393 | - File **all-accetto.js** removed because the related functionality doesn't seem to be supported any more 394 | - related scripts updated accordingly 395 | - Firefox version **67.0.1** 396 | 397 | ### Version 19.05 398 | 399 | - Fixed [Issue #2](https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus/issues/2) (How to run as non-root user) (actually the **issue #8** of the [base image][this-base]) 400 | - **Dockerfile** updated 401 | - user permissions set using `set_user_permissions.sh` script (inherited from the [base image][this-base]) 402 | - Launchers for **Vim** and **TigerVNC Viewer** added to the desktop (inherited from the [base image][this-base]) 403 | - Utility `util-hdx.sh` updated (using [accetto/argbash-docker][accetto-docker-argbash-docker]) 404 | 405 | ### Version 19.04 406 | 407 | - **noVNC** updated to version **1.1.0** (formerly 1.0.0), inherited from the [base image][this-base] 408 | - **ping** utility added, inherited from the [base image][this-base] 409 | - Environment variable **REFRESHED_AT** added back 410 | - Display settings launcher added to the desktop and the panels 411 | - to make resolution switching more convenient also with **noVNC** lite client 412 | - inherited from the [base image][this-base] 413 | - **Dockerfile_rolling** file removed 414 | - it can be easily cloned from the Dockerfile file for the **latest** build 415 | - **rolling** build will not be maintained on **Docker Hub** any more 416 | 417 | ### Version 19.01 418 | 419 | - **TigerVNC** updated to version **1.9.0** (formerly 1.8.0), inherited from the [base image][this-base] 420 | - **websockify** updated to version **0.8.0** (formerly 0.6.1), inherited from the [base image][this-base] 421 | - Environment variable **REFRESHED_AT** removed 422 | - Xfce panels are pre-configured now 423 | - container screenshot added to README 424 | - **Firefox Quantum** version **64.0** (gets updated to the current version on each re-build) 425 | 426 | ### Version 18.10 427 | 428 | - Fixed **Issue #7** (Problem with foreground mode) inherited from the [base image][this-base] 429 | - supported startup options: `--wait` (default), `--skip`, `--debug` (also `--tail-log`) and `--help` 430 | - getting help: `docker run --rm accetto/ubuntu-vnc-xfce --help` 431 | - README file is extended 432 | 433 | ### Version 18.06 434 | 435 | - Dockerfile redesigned 436 | - multi-staged and explicit 437 | - helper installation scripts mostly removed 438 | - Some other changes inherited from the [base image][this-base] 439 | - standard *Xfce* desktop, incl. initial panel configuration on the first start 440 | - editor **leafpad** replaced by more advanced but still lite [mousepad][mousepad] 441 | - **pulseaudio** and **pavucontrol** not purged any more 442 | - Firefox updated 443 | 444 | ### Version 18.05.2 445 | 446 | - Dockerfiles - build arguments and environment variables interaction redesigned 447 | - Default **VNC_RESOLUTION=1024x768** and it can be set also through build arguments 448 | 449 | ### Version 18.05.1 450 | 451 | - Firefox Quantum updated to version **60.0** (64-bit) 452 | 453 | ### Version 18.05 454 | 455 | - This is the first version after splitting from the former common base repository [accetto/ubuntu-vnc-xfce][accetto-github-ubuntu-vnc-xfce] 456 | - Resources for base Ubuntu/VNC images and images with configurable Firefox split into separate GitHub repositories, consequently 457 | - README, CHANGELOG and Wiki are not common any more 458 | - Resources for base images moved to repository [accetto/ubuntu-vnc-xfce][accetto-github-ubuntu-vnc-xfce] 459 | - Resources for images with default Firefox installation moved to repository [accetto/ubuntu-vnc-xfce-firefox][accetto-github-ubuntu-vnc-xfce-firefox] 460 | - This image contains Firefox installation with pre-configuration support 461 | 462 | *** 463 | 464 | [this-docker]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-firefox-plus/ 465 | [this-github]: https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus 466 | [this-base]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce 467 | [this-wiki]: https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus/wiki 468 | 469 | [that-wiki-firefox-multiprocess]: https://github.com/accetto/xubuntu-vnc/wiki/Firefox-multiprocess 470 | 471 | [accetto-github-ubuntu-vnc-xfce]: https://github.com/accetto/ubuntu-vnc-xfce 472 | [accetto-github-ubuntu-vnc-xfce-firefox]: https://github.com/accetto/ubuntu-vnc-xfce-firefox 473 | 474 | [accetto-ubuntu-vnc-xfce-g3]: https://github.com/accetto/ubuntu-vnc-xfce-g3 475 | 476 | [accetto-docker-xubuntu-vnc]: https://hub.docker.com/r/accetto/xubuntu-vnc 477 | [accetto-docker-xubuntu-vnc-firefox]:https://hub.docker.com/r/accetto/xubuntu-vnc-firefox 478 | 479 | [accetto-docker-argbash-docker]: https://hub.docker.com/r/accetto/argbash-docker 480 | [accetto-github-argbash-docker]: https://github.com/accetto/argbash-docker 481 | 482 | [accetto-tigervnc-release-mirror]: https://github.com/accetto/tigervnc/releases 483 | 484 | [mousepad]: https://github.com/codebrainz/mousepad 485 | [novnc]: https://github.com/kanaka/noVNC 486 | [nsswrapper]: https://cwrap.org/nss_wrapper.html 487 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Headless Ubuntu/Xfce container with VNC/noVNC and configurable Firefox 2 | 3 | ## accetto/ubuntu-vnc-xfce-firefox-plus 4 | 5 | [Docker Hub][this-docker] - [Git Hub][this-github] - [Changelog][this-changelog] - [Wiki][this-wiki] 6 | 7 | *** 8 | 9 | **Remark** The repository has been revived and merged into the repository [ubuntu-vnc-xfce][accetto-github-ubuntu-vnc-xfce], because I've noticed, that the images are still being pulled. This original repository [ubuntu-vnc-xfce-firefox-plus][this-github] stays retired. 10 | 11 | **Attention!** The repository is **retired** and **archived**. It will not be developed any further and the related images on Docker Hub will not be rebuilt any more. They will phase out and they will be deleted after becoming too old. Please use the newer **third generation** (G3) repository [accetto/ubuntu-vnc-xfce-g3][accetto-ubuntu-vnc-xfce-g3] and the related images on Docker Hub instead. If you still need images based on `Ubuntu 18.04 LTS`, then feel free using the repository for building the images locally. 12 | 13 | *** 14 | 15 | ![badge-docker-pulls][badge-docker-pulls] 16 | ![badge-docker-stars][badge-docker-stars] 17 | ![badge-github-release][badge-github-release] 18 | ![badge-github-release-date][badge-github-release-date] 19 | ![badge-github-stars][badge-github-stars] 20 | ![badge-github-forks][badge-github-forks] 21 | ![badge-github-open-issues][badge-github-open-issues] 22 | ![badge-github-closed-issues][badge-github-closed-issues] 23 | ![badge-github-releases][badge-github-releases] 24 | ![badge-github-commits][badge-github-commits] 25 | ![badge-github-last-commit][badge-github-last-commit] 26 | 27 | **Tip** If you want newer images based on [Ubuntu 20.04 LTS][docker-ubuntu] with the latest [TigerVNC][tigervnc-releases]/[noVNC][novnc-releases] versions, please check the **third generation** (G3) [accetto/ubuntu-vnc-xfce-g3][accetto-docker-ubuntu-vnc-xfce-g3], [accetto/ubuntu-vnc-xfce-chromium-g3][accetto-docker-ubuntu-vnc-xfce-chromium-g3] or [accetto/ubuntu-vnc-xfce-firefox-g3][accetto-docker-ubuntu-vnc-xfce-firefox-g3]. 28 | 29 | **Tip** Unless you need [nss_wrapper][nsswrapper], you can also use my newer image [accetto/xubuntu-vnc-novnc-firefox][accetto-docker-xubuntu-vnc-novnc-firefox], which is a streamlined version of this image ([image hierarchy][accetto-xubuntu-vnc-novnc-wiki-image-hierarchy]). If you also don't need [noVNC][novnc], you can use even a slimmer image [accetto/xubuntu-vnc-firefox][accetto-docker-xubuntu-vnc-firefox], which is a member of another growing family of application images ([image hierarchy][accetto-xubuntu-vnc-wiki-image-hierarchy]). The newer images include also **sudo** command. 30 | 31 | *** 32 | 33 | **WARNING** about images with Firefox 34 | 35 | Starting from the release **20.10.1**, there is no single-process Firefox image 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][that-wiki-firefox-multiprocess] page in Wiki for more information and the instructions, how to set the shared memory size in different scenarios. 36 | 37 | *** 38 | 39 | **Attention:** Resources for building images with default Firefox installation without configuration support can be found in its own GitHub repository [ubuntu-vnc-xfce-firefox][accetto-github-ubuntu-vnc-xfce-firefox]. Resources for building base images are in the GitHub repository [accetto/ubuntu-vnc-xfce][accetto-github-ubuntu-vnc-xfce]. 40 | 41 | **This repository** contains resources for building a Docker image based on [Ubuntu][docker-ubuntu] with [Xfce][xfce] desktop environment, **VNC**/[noVNC][novnc] servers for headless use and the current [Firefox][firefox] web browser with pre-configuration support. 42 | 43 | The image can be successfully built and used on Linux, Windows, Mac and NAS devices. It has been tested with [Docker Desktop][docker-desktop] on [Ubuntu flavours][ubuntu-flavours], [Windows 10][docker-for-windows] and [Container Station][container-station] from [QNAP][qnap]. 44 | 45 | Containers created from this image make perfect light-weight web browsers. They can be thrown away easily and replaced quickly, improving browsing privacy. They run under a non-root user by default, improving browsing security. 46 | 47 | They make also excellent long-term browsers, because the preferences and profiles can be pre-configured and stored on volumes that survive container destruction. 48 | 49 | There are two ways of customization. Firstly, it's possible to force Firefox preferences by modifying the provided **user.js** file. Secondly, it's possible to use a complete Firefox profile, previously created on a volume. The [HOWTO][this-wiki-howto] page in [Wiki][this-wiki] describes it in more details. 50 | 51 | Frequently used preferences and profiles can be also embedded into new customized images, built by the user. The ready-to-use Dockerfiles are already provided (see [below](#user-content-image-set)). The [HOWTO][this-wiki-howto] page in [Wiki][this-wiki] describes how to build such images. 52 | 53 | Running in background is the primary scenario for the containers, but using them interactively in foreground is also possible. For examples see the description below or the [HOWTO][this-wiki-howto] section in [Wiki][this-wiki]. 54 | 55 | The image is based on the [accetto/ubuntu-vnc-xfce][accetto-docker-ubuntu-vnc-xfce] image, just adding the [Firefox][firefox] browser and the resources for its customization. 56 | 57 | The image inherits the following components from its [base image][accetto-docker-ubuntu-vnc-xfce]: 58 | 59 | - utilities **ping**, **wget**, **zip**, **unzip**, [curl][curl], [git][git] (Ubuntu distribution) 60 | - current version of JSON processor [jq][jq] 61 | - light-weight [Xfce][xfce] desktop environment (Ubuntu distribution) 62 | - current version of high-performance [TigerVNC][tigervnc] server and client 63 | - current version of [noVNC][novnc] HTML5 clients (full and lite) (TCP port **6901**) 64 | - popular text editors [vim][vim] and [nano][nano] (Ubuntu distribution) 65 | - lite but advanced graphical editor [mousepad][mousepad] (Ubuntu distribution) 66 | - support of **version sticker** (see below) 67 | 68 | **Please note** that **Firefox 67** has changed default profile handling and therefore the pre-created folder `profile0.default`, which contains the file `user.js` with user preferences, will not be used automatically, until you explicitly choose the folder before the first Firefox start. The other option is to copy the user preferences afterwards using the provided script. You can find more information about it in the [issue #3][this-issue-3]. 69 | 70 | The following desktop launchers have been added for your convenience: 71 | 72 | - **FF Profile Manager** starts the Firefox with the argument **-P** so you can choose Firefox profiles or create new ones conveniently. It is recommended to choose the pre-created profile folder `profile0.default` before the first Firefox start. Note that it shows up as the **default** profile in the Profile Manager's list and that the actual profile data will be created by the Firefox itself. 73 | - **Copy FF Preferences** starts the script for copying the file **user.js**, containing your own Firefox preferences, to one or more Firefox profiles interactively. You can use it if you haven't chosen the profile before the first Firefox start or you have created new ones later. 74 | 75 | Running containers in background is the primary scenario this image has been developed for. However, running in foreground can be useful in many cases. See the description below for examples of using the containers both ways. 76 | 77 | The image is regularly maintained and rebuilt. The history of notable changes is documented in [CHANGELOG][this-changelog]. 78 | 79 | ![screenshot-container][screenshot-container] 80 | 81 | ### Image set 82 | 83 | - [accetto/ubuntu-vnc-xfce-firefox-plus][this-docker] 84 | 85 | - `latest` based on `accetto/ubuntu-vnc-xfce:latest` 86 | 87 | ![badge-VERSION_STICKER_LATEST][badge-VERSION_STICKER_LATEST] 88 | 89 | - **accetto/ubuntu-vnc-xfce-firefox-plus-preferences** 90 | 91 | This image is not actually contained in the [Docker repository][accetto-docker], because it is intended to keep pre-configured user-specific **Firefox preferences**. Users can put their favorite preferences into the configuration files and build the image using the provided [Dockerfile-plus-preferences][this-dockerfile-plus-preferences]. The [HOWTO][this-wiki-howto] page in [Wiki][this-wiki] describes it in more details. 92 | 93 | - **accetto/ubuntu-vnc-xfce-firefox-plus-profile** 94 | 95 | This image is also not actually contained in the [Docker repository][accetto-docker], because it is intended to keep pre-configured user-specific **Firefox profiles**. Users can prepare a full Firefox profile and build the image using the provided [Dockerfile-plus-profile][this-dockerfile-plus-profile]. The [HOWTO][this-wiki-howto] page in [Wiki][this-wiki] describes it in more details. 96 | 97 | ### Ports 98 | 99 | Following **TCP** ports are exposed: 100 | 101 | - **5901** used for access over **VNC** 102 | - **6901** used for access over [noVNC][novnc] 103 | 104 | The default **VNC user** password is **headless**. 105 | 106 | ### Volumes 107 | 108 | The containers do not create or use any external volumes by default. However, the following folders make good mounting points: 109 | 110 | - /home/headless/Documents/ 111 | - /home/headless/Downloads/ 112 | - /home/headless/Music/ 113 | - /home/headless/Pictures/ 114 | - /home/headless/Public/ 115 | - /home/headless/Templates/ 116 | - /home/headless/Videos/ 117 | 118 | The following mounting point is specific to Firefox: 119 | 120 | - /home/headless/.mozilla 121 | 122 | Both *named volumes* and *bind mounts* can be used. More about volumes can be found in [Docker documentation][docker-doc] (e.g. [Manage data in Docker][docker-doc-managing-data]). 123 | 124 | ### Version sticker 125 | 126 | Version sticker serves multiple purposes that are closer described in [Wiki][this-wiki]. The **version sticker value** identifies the version of the docker image and it is persisted in it when it is built. It is also shown as a badge in the README file. 127 | 128 | However, the script `version_sticker.sh` can be used anytime for convenient checking of the current versions of installed applications. 129 | 130 | The script is deployed into the startup folder, which is defined by the environment variable `STARTUPDIR` with the default value of `/dockerstartup`. 131 | 132 | If the script is executed inside a container without an argument, then it returns the **current version sticker value** of the container. This value is newly calculated and it is based on the current versions of the essential applications in the container. 133 | 134 | The **current** version sticker value will differ from the **persisted** value, if any of the included application has been updated to another version. 135 | 136 | If the script is called with the argument `-v` (lower case `v`), then it prints out verbose versions of the essential applications that are included in the **version sticker value**. 137 | 138 | If it is called with the argument `-V` (upper case `v`), then it prints out verbose versions of some more applications. 139 | 140 | Examples can be found in [Wiki][this-wiki]. 141 | 142 | ## Firefox multi-process 143 | 144 | 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.**). 145 | 146 | 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. 147 | 148 | Mozilla has fixed the problem in the next release, but they warned about not supporting the switch in future. That is why I've decided, that the mainstream image tagged as `latest` 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. 149 | 150 | For some time I've maintained also `singleprocess` images intended for scenarios, where increasing the shared memory size is not possible or not wanted. However, by Firefox **81.0** I've noticed, that the environment variable **MOZ_FORCE_DISABLE_E10S** has no effect any more. Since then all images run Firefox in multi-process mode. 151 | 152 | 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. 153 | 154 | ### Setting shared memory size 155 | 156 | 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. 157 | 158 | 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. 159 | 160 | For example, the following container will have its shared memory size set to 256MB: 161 | 162 | ```bash 163 | docker run -d -P --shm-size=256m accetto/xubuntu-vnc-xfce-firefox-plus 164 | ``` 165 | 166 | You can check the current shared memory size by executing the following command inside the container: 167 | 168 | ```bash 169 | df -h /dev/shm 170 | ``` 171 | 172 | ## Running containers in background (detached) 173 | 174 | Created containers will run under the non-root user **headless:headless** by default. 175 | 176 | The following container will listen on automatically selected **TCP** ports of the host computer: 177 | 178 | ```docker 179 | docker run -d -P accetto/ubuntu-vnc-xfce-firefox-plus 180 | ``` 181 | 182 | The following container will listen on the host's **TCP** ports **25901** (VNC) and **26901** (noVNC): 183 | 184 | ```docker 185 | docker run -d -p 25901:5901 -p 26901:6901 accetto/ubuntu-vnc-xfce-firefox-plus 186 | ``` 187 | 188 | The following container wil create or re-use the local named volume **my\_Downloads** mounted as `/home/headless/Downloads`. The container will be accessible through the same **TCP** ports as the one above: 189 | 190 | ```docker 191 | docker run -d -P -v my_Downloads:/home/headless/Downloads accetto/ubuntu-vnc-xfce-firefox-plus 192 | ``` 193 | 194 | or using the newer syntax with **--mount** flag: 195 | 196 | ```docker 197 | docker run -d -P --mount source=my_Downloads,target=/home/headless/Downloads accetto/ubuntu-vnc-xfce-firefox-plus 198 | ``` 199 | 200 | More usage examples can be found in [Wiki][this-wiki] (section [HOWTO][this-wiki-howto]). 201 | 202 | ## Running containers in foreground (interactively) 203 | 204 | The image supports the following container start-up options: `--wait` (default), `--skip`, `--debug` (also `--tail-log`) and `--help`. This functionality is inherited from the [base image][accetto-docker-ubuntu-vnc-xfce]. 205 | 206 | The following container will print out the help and then it'll remove itself: 207 | 208 | ```docker 209 | docker run --rm accetto/ubuntu-vnc-xfce-firefox-plus --help 210 | ``` 211 | 212 | Excerpt from the output, which describes the other options: 213 | 214 | ```docker 215 | OPTIONS: 216 | -w, --wait (default) Keeps the UI and the vnc server up until SIGINT or SIGTERM are received. 217 | An optional command can be executed after the vnc starts up. 218 | example: docker run -d -P accetto/ubuntu-vnc-xfce 219 | example: docker run -it -P --rm accetto/ubuntu-vnc-xfce bash 220 | 221 | -s, --skip Skips the vnc startup and just executes the provided command. 222 | example: docker run -it -P --rm accetto/ubuntu-vnc-xfce --skip echo $BASH_VERSION 223 | 224 | -d, --debug Executes the vnc startup and tails the vnc/noVNC logs. 225 | Any parameters after '--debug' are ignored. CTRL-C stops the container. 226 | example: docker run -it -P --rm accetto/ubuntu-vnc-xfce --debug 227 | 228 | -t, --tail-log same as '--debug' 229 | 230 | -h, --help Prints out this help. 231 | example: docker run --rm accetto/ubuntu-vnc-xfce 232 | ``` 233 | 234 | It should be noticed, that the `--debug` start-up option does not show the command prompt even if the `-it` run arguments are provided. This is because the container is watching the incoming vnc/noVNC connections and prints out their logs in real time. However, it is easy to attach to the running container like in the following example. 235 | 236 | In the first terminal window on the host computer, create a new container named **foo**: 237 | 238 | ```docker 239 | docker run --name foo accetto/ubuntu-vnc-xfce-firefox-plus --debug 240 | ``` 241 | 242 | In the second terminal window on the host computer, execute the shell inside the **foo** container: 243 | 244 | ```docker 245 | docker exec -it foo /bin/bash 246 | ``` 247 | 248 | ## Using headless containers 249 | 250 | There are two ways, how to use the created headless containers. Note that the default **VNC user** password is **headless**. 251 | 252 | ### Over VNC 253 | 254 | To be able to use the containers over **VNC**, a **VNC Viewer** is needed (e.g. [TigerVNC][tigervnc] or [TightVNC][tightvnc]). 255 | 256 | The VNC Viewer should connect to the host running the container, pointing to the host's TCP port mapped to the container's TCP port **5901**. 257 | 258 | 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`. 259 | 260 | ### Over noVNC 261 | 262 | 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. 263 | 264 | The browser should navigate to the host running the container, pointing to the host's TCP port mapped to the container's TCP port **6901**. 265 | 266 | However, the containers offer two [noVNC][novnc] clients - **lite** and **full**. The connection URL differs slightly in both cases. To make it easier, a simple startup page is implemented. 267 | 268 | If the container have been created on the host called `mynas` using the parameters described above, then the web browser should navigate to `http://mynas:26901`. 269 | 270 | The startup page will show two hyperlinks pointing to the both noVNC clients: 271 | 272 | - `http://mynas:26901/vnc_lite.html` 273 | - `http://mynas:26901/vnc.html` 274 | 275 | It's also possible to provide the password through the links: 276 | 277 | - `http://mynas:26901/vnc_lite.html?password=headless` 278 | - `http://mynas:26901/vnc.html?password=headless` 279 | 280 | ## Issues 281 | 282 | If you have found a problem or you just have a question, please check the [Issues][this-issues] and the [Troubleshooting][this-wiki-troubleshooting], [FAQ][this-wiki-faq] and [HOWTO][this-wiki-howto] sections in [Wiki][this-wiki] first. Please do not overlook the closed issues. 283 | 284 | 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. 285 | 286 | ## Credits 287 | 288 | Credit goes to all the countless people and companies who contribute to open source community and make so many dreamy things real. 289 | 290 | *** 291 | 292 | [this-docker]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-firefox-plus/ 293 | [this-github]: https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus 294 | 295 | [this-changelog]: https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus/blob/master/CHANGELOG.md 296 | 297 | [this-issues]: https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus/issues 298 | [this-issue-3]: https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus/issues/3 299 | 300 | [this-wiki]: https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus/wiki 301 | [this-wiki-howto]: https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus/wiki/How-to 302 | [this-wiki-troubleshooting]: https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus/wiki/Troubleshooting 303 | [this-wiki-faq]: https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus/wiki/Frequently-asked-questions 304 | 305 | [that-wiki-firefox-multiprocess]: https://github.com/accetto/xubuntu-vnc/wiki/Firefox-multiprocess 306 | 307 | [this-dockerfile-plus-preferences]: https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus/blob/master/Dockerfile-plus-preferences 308 | [this-dockerfile-plus-profile]: https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus/blob/master/Dockerfile-plus-profile 309 | 310 | [accetto-github]: https://github.com/accetto/ 311 | [accetto-docker]: https://hub.docker.com/u/accetto/ 312 | 313 | [accetto-github-ubuntu-vnc-xfce]: https://github.com/accetto/ubuntu-vnc-xfce 314 | [accetto-docker-ubuntu-vnc-xfce]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce/ 315 | 316 | [accetto-github-ubuntu-vnc-xfce-firefox]: https://github.com/accetto/ubuntu-vnc-xfce-firefox/ 317 | 318 | [accetto-docker-xubuntu-vnc-firefox]:https://hub.docker.com/r/accetto/xubuntu-vnc-firefox 319 | [accetto-xubuntu-vnc-wiki-image-hierarchy]: https://github.com/accetto/xubuntu-vnc/wiki/Image-hierarchy 320 | 321 | [accetto-ubuntu-vnc-xfce-g3]: https://github.com/accetto/ubuntu-vnc-xfce-g3 322 | 323 | [accetto-docker-ubuntu-vnc-xfce-g3]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-g3 324 | [accetto-docker-ubuntu-vnc-xfce-chromium-g3]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-chromium-g3 325 | [accetto-docker-ubuntu-vnc-xfce-firefox-g3]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-firefox-g3 326 | 327 | [accetto-docker-xubuntu-vnc-novnc-firefox]: https://hub.docker.com/r/accetto/xubuntu-vnc-novnc-firefox 328 | [accetto-xubuntu-vnc-novnc-wiki-image-hierarchy]: https://github.com/accetto/xubuntu-vnc-novnc/wiki/Image-hierarchy 329 | 330 | [docker-ubuntu]: https://hub.docker.com/_/ubuntu/ 331 | [docker-doc]: https://docs.docker.com/ 332 | [docker-doc-managing-data]: https://docs.docker.com/storage/ 333 | [docker-for-windows]: https://hub.docker.com/editions/community/docker-ce-desktop-windows 334 | [docker-desktop]: https://www.docker.com/products/docker-desktop 335 | 336 | [qnap]: https://www.qnap.com/en/ 337 | [container-station]: https://www.qnap.com/solution/container_station/en/ 338 | 339 | [ubuntu-flavours]: https://www.ubuntu.com/download/flavours 340 | 341 | [curl]: http://manpages.ubuntu.com/manpages/bionic/man1/curl.1.html 342 | [firefox]: https://www.mozilla.org 343 | [git]: https://git-scm.com/ 344 | [jq]: https://stedolan.github.io/jq/ 345 | [mousepad]: https://github.com/codebrainz/mousepad 346 | [nano]: https://www.nano-editor.org/ 347 | [novnc]: https://github.com/kanaka/noVNC 348 | [novnc-releases]: https://github.com/novnc/noVNC/releases 349 | [nsswrapper]: https://cwrap.org/nss_wrapper.html 350 | [tigervnc]: http://tigervnc.org 351 | [tigervnc-releases]: https://github.com/TigerVNC/tigervnc/releases 352 | [tightvnc]: http://www.tightvnc.com 353 | [vim]: https://www.vim.org/ 354 | [xfce]: http://www.xfce.org 355 | 356 | [screenshot-container]: https://raw.githubusercontent.com/accetto/ubuntu-vnc-xfce-firefox-plus/master/ubuntu-vnc-xfce-firefox-plus.jpg 357 | 358 | 359 | 360 | [badge-docker-pulls]: https://badgen.net/docker/pulls/accetto/ubuntu-vnc-xfce-firefox-plus?icon=docker&label=pulls 361 | 362 | [badge-docker-stars]: https://badgen.net/docker/stars/accetto/ubuntu-vnc-xfce-firefox-plus?icon=docker&label=stars 363 | 364 | 365 | 366 | [badge-github-release]: https://badgen.net/github/release/accetto/ubuntu-vnc-xfce-firefox-plus?icon=github&label=release 367 | 368 | [badge-github-release-date]: https://img.shields.io/github/release-date/accetto/ubuntu-vnc-xfce-firefox-plus?logo=github 369 | 370 | [badge-github-stars]: https://badgen.net/github/stars/accetto/ubuntu-vnc-xfce-firefox-plus?icon=github&label=stars 371 | 372 | [badge-github-forks]: https://badgen.net/github/forks/accetto/ubuntu-vnc-xfce-firefox-plus?icon=github&label=forks 373 | 374 | [badge-github-releases]: https://badgen.net/github/releases/accetto/ubuntu-vnc-xfce-firefox-plus?icon=github&label=releases 375 | 376 | [badge-github-commits]: https://badgen.net/github/commits/accetto/ubuntu-vnc-xfce-firefox-plus?icon=github&label=commits 377 | 378 | [badge-github-last-commit]: https://badgen.net/github/last-commit/accetto/ubuntu-vnc-xfce-firefox-plus?icon=github&label=last%20commit 379 | 380 | [badge-github-closed-issues]: https://badgen.net/github/closed-issues/accetto/ubuntu-vnc-xfce-firefox-plus?icon=github&label=closed%20issues 381 | 382 | [badge-github-open-issues]: https://badgen.net/github/open-issues/accetto/ubuntu-vnc-xfce-firefox-plus?icon=github&label=open%20issues 383 | 384 | 385 | 386 | [badge-VERSION_STICKER_LATEST]: https://badgen.net/badge/version%20sticker/ubuntu18.04.6-firefox98.0/blue 387 | --------------------------------------------------------------------------------