├── .gitattributes ├── get_release_info.sh ├── supervisord.conf ├── menu.xml ├── .github └── workflows │ └── docker.yml ├── get_latest_cura_release.sh ├── README.md └── Dockerfile /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | /docker/* text eol=lf 4 | /ci/* text eol=lf 5 | /sbt text eol=lf 6 | /docker-*.sh text eol=lf 7 | /sbt-dist/bin/*.bash text eol=lf 8 | /sbt-dist/bin/sbt text eol=lf -------------------------------------------------------------------------------- /get_release_info.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TMPDIR="$(mktemp -d)" 4 | 5 | curl -SsL https://api.github.com/repos/Ultimaker/Cura/releases/latest > $TMPDIR/latest.json 6 | 7 | url=$(jq -r '.assets[] | select(.browser_download_url|test("-linux-X64.AppImage$"))| .browser_download_url' $TMPDIR/latest.json) 8 | name=$(jq -r '.assets[] | select(.browser_download_url|test("-linux-X64.AppImage$"))| .name' $TMPDIR/latest.json) 9 | version=$(jq -r .tag_name $TMPDIR/latest.json) 10 | 11 | if [ $# -ne 1 ]; then 12 | echo wrong number of params 13 | exit 1 14 | else 15 | request=$1 16 | fi 17 | 18 | case $request in 19 | 20 | url) 21 | echo $url 22 | ;; 23 | 24 | name) 25 | echo $name 26 | ;; 27 | 28 | version) 29 | echo $version 30 | ;; 31 | 32 | *) 33 | echo "Unknown request" 34 | ;; 35 | esac 36 | 37 | exit 0 -------------------------------------------------------------------------------- /supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | pidfile=/tmp/supervisord.pid 4 | 5 | [program:x11] 6 | priority=0 7 | command=/usr/bin/Xtigervnc -desktop "Cura" -rfbport 5900 -SecurityTypes None -AlwaysShared -AcceptKeyEvents -AcceptPointerEvents -AcceptSetDesktopSize -SendCutText -AcceptCutText :0 8 | autorestart=true 9 | redirect_stderr=true 10 | 11 | [program:easy-novnc] 12 | priority=0 13 | command=/usr/local/bin/easy-novnc --addr :8080 --host localhost --port 5900 --no-url-password --novnc-params "resize=remote" 14 | autorestart=true 15 | redirect_stderr=true 16 | 17 | [program:openbox] 18 | priority=1 19 | command=/usr/bin/openbox 20 | environment=DISPLAY=:0 21 | autorestart=true 22 | redirect_stderr=true 23 | 24 | [program:cura] 25 | priority=1 26 | environment=DISPLAY=:0 27 | command=/bin/bash -c '/cura/squashfs-root/AppRun' 28 | autorestart=true 29 | redirect_stderr=true -------------------------------------------------------------------------------- /menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /cura/squashfs-root/AppRun 7 | 8 | 9 | 10 | 11 | /usr/bin/x-terminal-emulator 12 | 13 | 14 | 15 | 16 | /usr/bin/pcmanfm 17 | 18 | 19 | 20 | 21 | /usr/bin/x-terminal-emulator -e htop 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /.github/workflows/docker.yml: -------------------------------------------------------------------------------- 1 | name: Build New Version 2 | 3 | on: 4 | schedule: 5 | - cron: 0 0 * * 5 6 | workflow_dispatch: {} 7 | 8 | jobs: 9 | push_to_registry: 10 | name: Push Docker image to Docker Hub 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Check out the repo 14 | uses: actions/checkout@v3 15 | 16 | - name: Log in to the Container registry 17 | uses: docker/login-action@v2 18 | with: 19 | username: ${{ secrets.DOCKER_USERNAME }} 20 | password: ${{ secrets.DOCKER_PASSWORD }} 21 | 22 | - name: Extract latest available Cura Version 23 | id: version 24 | run: echo "version=$(sh get_release_info.sh version)" |tee -a $GITHUB_OUTPUT 25 | 26 | - name: Check if this release already exists 27 | uses: mukunku/tag-exists-action@v1.2.0 28 | id: checktag 29 | with: 30 | tag: ${{ steps.version.outputs.version }} 31 | 32 | - name: Create new tag with Cura Version 33 | uses: rickstaa/action-create-tag@v1 34 | id: tag_create 35 | if: ${{ steps.checktag.outputs.exists == 'false' }} 36 | with: 37 | tag: ${{ steps.version.outputs.version }} 38 | tag_exists_error: false 39 | message: New Cura Release ${{ steps.version.outputs.version }} 40 | 41 | - name: Build and push Container 42 | uses: docker/build-push-action@v4 43 | if: ${{ steps.checktag.outputs.exists == 'false' }} 44 | with: 45 | context: . 46 | push: true 47 | tags: mikeah/cura-novnc:latest, mikeah/cura-novnc:${{ steps.version.outputs.version }} 48 | -------------------------------------------------------------------------------- /get_latest_cura_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Get the latest release of Cura for Linux (AppImage) using the GitHub API 3 | # This was forked from https://github.com/dmagyar/prusaslicer-vnc-docker/blob/main/getLatestPrusaSlicerRelease.sh 4 | 5 | set -eu 6 | 7 | if [[ $# -lt 1 ]]; then 8 | echo "~~~ $0 ~~~" 9 | echo " usage: $0 [ url | name | url_ver VERSION | name_ver VERSION_NAME ]" 10 | echo 11 | echo " url: Returns the download URL for the latest release (for download using cURL/wget)" 12 | echo " name: Returns the filename of the latest release" 13 | echo 14 | echo " url_ver: Takes a parameter to specify the version to retrieve (note: some download urls have hex-encoded ascii characters)" 15 | echo " url_ver example: $0 url_ver 2.0.0%2B" 16 | echo " output: https://github.com/prusa3d/PrusaSlicer/releases/download/version_2.0.0/PrusaSlicer-2.0.0%2Blinux64-201905201652.tar.bz2" 17 | echo 18 | echo " name_ver: Takes a parameter to specify the filename to retrieve (note: this has a '+' added on at the end of the provided version number)" 19 | echo " name_ver example: $0 name_ver 2.0.0" 20 | echo " output: PrusaSlicer-2.0.0+linux64-201905201652.tar.bz2" 21 | echo 22 | exit 1 23 | fi 24 | 25 | baseDir="~/testing_cura" 26 | mkdir -p $baseDir 27 | 28 | if [[ ! -e "$baseDir/latestReleaseInfo.json" ]]; then 29 | 30 | curl -SsL https://api.github.com/repos/Ultimaker/Cura/releases/latest > $baseDir/latestReleaseInfo.json 31 | 32 | fi 33 | 34 | releaseInfo=$(cat $baseDir/latestReleaseInfo.json) 35 | 36 | if [[ $# -gt 1 ]]; then 37 | 38 | VER=$2 39 | 40 | if [[ ! -e "$baseDir/releases.json" ]]; then 41 | curl -SsL https://api.github.com/repos/Ultimaker/Cura/releases > $baseDir/releases.json 42 | fi 43 | 44 | allReleases=$(cat $baseDir/releases.json) 45 | 46 | fi 47 | 48 | if [[ "$1" == "url" ]]; then 49 | echo "${releaseInfo}" | jq -r '.assets[] | .browser_download_url | select(test("Ultimaker-Cura-.+(-\\w)?+linux.AppImage?.(?!.)"))' 50 | 51 | elif [[ "$1" == "name" ]]; then 52 | 53 | echo "${releaseInfo}" | jq -r '.assets[] | .name | select(test("Ultimaker-Cura-.+(-\\w)?+linux.AppImage?.(?!.)"))' 54 | 55 | elif [[ "$1" == "url_ver" ]]; then 56 | 57 | # Note: Releases sometimes have hex-encoded ascii characters tacked on 58 | # So version '2.0.0+' might need to be requested as '2.0.0%2B' since GitHub returns that as the download URL 59 | echo "${allReleases}" | jq --arg VERSION "$VER" -r '.[] | .assets[] | .browser_download_url | select(test(Ultimaker-Cura-" + $VERSION + "+.AppImage?.(?!.)"))' 60 | 61 | fi -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cura noVNC Docker Container 2 | 3 | ## Overview 4 | 5 | This is a super basic noVNC build using supervisor to serve Cura in your favorite web browser. This was primarily built for users using the [popular unraid NAS software](https://unraid.net), to allow them to quickly hop in a browser, slice, and upload their favorite 3D prints. 6 | 7 | This is super similar to my [prusaslicer-novnc](https://github.com/helfrichmichael/prusaslicer-novnc) container and basically just adapts that for using Cura via VNC. 8 | 9 | Please note: This is a work-in-progress and the Docker image is larger than I'd like it to be. More updates to come soon. Specifically the image is using the extracted AppImage version which results in extra copies of dependencies that might already exist. 10 | 11 | ## How to use 12 | 13 | **In unraid** 14 | 15 | If you're using unraid, open your Docker page and under `Template repositories`, add `https://github.com/helfrichmichael/unraid-templates` and save it. You should then be able to Add Container for cura-novnc. For unraid, the template will default to 6080 for the noVNC web instance. 16 | 17 | **Outside of unraid** 18 | 19 | To run this image, you can run the following command: `docker run --detach --volume=cura-novnc-data:/home/cura/ --volume=cura-novnc-prints:/prints/ -p 8080:8080 --name=cura-novnc cura-novnc` 20 | 21 | This will bind `/home/cura/` in the container to a local volume on my machine named `cura-novnc-data`. Additionally it will bind `/prints/` in the container to `cura-novnc-prints` locally on my machine. Finally it will bind port `8080` to `8080`. 22 | 23 | **Using a VNC Viewer** 24 | 25 | To use a VNC viewer with the container, the default port for X TigerVNC is 5900. You can add this port by adding `-p 5900:5900` to your command to start the container to open this port for access. 26 | 27 | 28 | **GPU Acceleration/Passthrough** 29 | 30 | Like other Docker containers, you can pass your Nvidia GPU into the container using the `NVIDIA_VISIBLE_DEVICES` and `NVIDIA_DRIVER_CAPABILITIES` envs. You can define these using the value of `all` or by providing more narrow and specific values. This has only been tested on Nvidia GPUs. 31 | 32 | In unraid you can set these values during set up. For containers outside of unraid, you can set this by adding the following params or similar `-e NVIDIA_DRIVER_CAPABILITIES="all" NVIDIA_VISIBLE_DEVICES="all"` 33 | 34 | 35 | ## Links 36 | 37 | [Cura](https://github.com/Ultimaker/Cura) 38 | 39 | [Supervisor](http://supervisord.org/) 40 | 41 | [GitHub Source](https://github.com/helfrichmichael/cura-novnc) 42 | 43 | [Docker](https://hub.docker.com/r/mikeah/cura-novnc) 44 | 45 | Buy Me A Coffee -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Get and install Easy noVNC. 2 | FROM golang:bullseye AS easy-novnc-build 3 | WORKDIR /src 4 | RUN go mod init build && \ 5 | go get github.com/geek1011/easy-novnc@v1.1.0 && \ 6 | go build -o /bin/easy-novnc github.com/geek1011/easy-novnc 7 | 8 | # Get TigerVNC and Supervisor for isolating the container. 9 | FROM debian:bullseye 10 | RUN apt-get update -y && \ 11 | apt-get install -y --no-install-recommends openbox tigervnc-standalone-server supervisor gosu && \ 12 | rm -rf /var/lib/apt/lists && \ 13 | mkdir -p /usr/share/desktop-directories 14 | 15 | # Get all of the remaining dependencies for the OS, VNC, and Cura (additionally Firefox-ESR to sign-in to Ultimaker if you'd like). 16 | RUN apt-get update -y && \ 17 | apt-get install -y --no-install-recommends openscad lxterminal nano wget openssh-client rsync ca-certificates xdg-utils htop tar xzip gzip bzip2 zip unzip && \ 18 | rm -rf /var/lib/apt/lists 19 | 20 | RUN apt update && apt install -y --no-install-recommends --allow-unauthenticated \ 21 | lxde gtk2-engines-murrine gnome-themes-standard gtk2-engines-pixbuf gtk2-engines-murrine arc-theme \ 22 | freeglut3 libgtk2.0-dev libwxgtk3.0-gtk3-dev libwx-perl libxmu-dev libgl1-mesa-glx libgl1-mesa-dri \ 23 | xdg-utils locales locales-all pcmanfm jq curl git firefox-esr qtbase5-dev \ 24 | && apt autoclean -y \ 25 | && apt autoremove -y \ 26 | && rm -rf /var/lib/apt/lists/* 27 | 28 | # Install Cura! 29 | ADD get_release_info.sh cura/ 30 | WORKDIR /cura 31 | 32 | RUN chmod +x /cura/get_release_info.sh \ 33 | && latestCura=$(/cura/get_release_info.sh url) \ 34 | && curaReleaseName=$(/cura/get_release_info.sh name) \ 35 | && curl -sSL ${latestCura} > ${curaReleaseName} \ 36 | && rm -f /cura/releaseInfo.json \ 37 | && chmod +x /cura/${curaReleaseName} \ 38 | && /cura/${curaReleaseName} --appimage-extract \ 39 | # Below, we adjust the platform theme to GTK3 per https://github.com/Ultimaker/Cura/issues/12266#issuecomment-1274861668. 40 | # Without this, the file dialog is never functional/visible with Cura due to the uncompiled App Image. 41 | && sed -i 's/QT_QPA_PLATFORMTHEME=xdgdesktopportal/QT_QPA_PLATFORMTHEME=gtk3/' /cura/squashfs-root/AppRun \ 42 | && rm /cura/${curaReleaseName} \ 43 | && rm -rf /var/lib/apt/lists/* \ 44 | && apt-get autoclean \ 45 | && groupadd cura \ 46 | && useradd -g cura --create-home --home-dir /home/cura cura \ 47 | && mkdir -p /cura \ 48 | && mkdir -p /prints/ \ 49 | && chown -R cura:cura /cura/ /home/cura/ /prints/ \ 50 | && mkdir -p /home/cura/.config/ \ 51 | # We can now set the Download directory for Firefox and other browsers. 52 | # We can also add /prints/ to the file explorer bookmarks for easy access. 53 | && echo "XDG_DOWNLOAD_DIR=\"/prints/\"" >> /home/cura/.config/user-dirs.dirs \ 54 | && echo "file:///prints prints" >> /home/cura/.gtk-bookmarks 55 | 56 | COPY --from=easy-novnc-build /bin/easy-novnc /usr/local/bin/ 57 | COPY menu.xml /etc/xdg/openbox/ 58 | COPY supervisord.conf /etc/ 59 | 60 | # HTTP Port 61 | EXPOSE 8080 62 | 63 | # VNC Port 64 | EXPOSE 5900 65 | 66 | VOLUME /home/cura/ 67 | VOLUME /prints/ 68 | 69 | # Enable printing with USB (https://github.com/helfrichmichael/cura-novnc/issues/7) 70 | RUN usermod -aG dialout cura 71 | 72 | # It's time! Let's get to work! We use /home/cura/ as a bindable volume for Cura and its configurations. We use /prints/ to provide a location for STLs and GCODE files. 73 | CMD ["/bin/bash", "-c", "chown -R cura:cura /home/cura/ /prints/ /dev/stdout && exec gosu cura supervisord"] 74 | --------------------------------------------------------------------------------