Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions docs/cloud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
title: Cloud Remote Access (Experimental)
---

# Cloud Remote Access (Experimental)

**Available in: Extended firmware only**

Control your printer remotely using cloud-based remote access providers.

> **Note**: Cloud providers are downloaded on-demand when enabled by the user. See [third-party integration design](design/third_party.md) for details on how external components are managed.

> **Warning**: This feature is experimental. Cloud services consume additional CPU and memory resources which may affect print quality or reliability during active prints. It is recommended to monitor system performance closely.

## Supported Providers

- **none** - Cloud access disabled (default)
- **octoeverywhere** - Remote access via [OctoEverywhere.com](https://octoeverywhere.com)

## OctoEverywhere

- Access your printer remotely from anywhere
- AI print failure detection and notifications
- Webcam streaming and timelapse
- Requires no port forwarding or VPN configuration

### Using firmware-config Web UI (preferred)

Navigate to the [firmware-config](firmware_config.md) web interface, go to the Remote Access section, and select OctoEverywhere under Cloud Provider. This will automatically download and install the OctoEverywhere plugin and display the account linking instructions.

### Manual Setup (advanced)

**Step 1:** Download OctoEverywhere (requires internet connection):
```bash
ssh root@<printer-ip>
octoeverywhere-pkg download
```

**Step 2:** Edit `extended/extended2.cfg`, set the `cloud`:
```ini
[remote_access]
cloud: octoeverywhere
```

**Step 3:** Start the cloud service:
```bash
/etc/init.d/S99cloud restart
```

**Step 4:** Link your account by downloading `octoeverywhere.log` from Mainsail or Fluidd to find the account linking URL. Open the URL in your browser to link your printer to your OctoEverywhere.com account.

**Need help?** Visit [OctoEverywhere Support for Snapmaker U1](https://octoeverywhere.com/s/snapmaker-u1) for assistance.
11 changes: 11 additions & 0 deletions docs/firmware_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Toggle settings directly from the web interface:
| Remote Screen | Enabled, Disabled | Enable remote screen access |
| Klipper Metrics Exporter | Enabled, Disabled | Enable Prometheus metrics |
| VPN Provider | None, Tailscale | Enable VPN remote access (Experimental) |
| Cloud | None, OctoEverywhere | Enable Cloud-based remote access (Experimental) |

Changes are applied immediately and relevant services are restarted.

Expand Down Expand Up @@ -160,6 +161,12 @@ Note: Remote screen requires additional Moonraker configuration. See [Remote Scr

See [VPN Remote Access](vpn.md) for setup instructions.

**cloud**
- `none` (default) - No cloud providers enabled.
- `octoeverywhere` - [OctoEverywhere.com](https://octoeverywhere.com) remote access

See the [3D Printing Clouds](cloud.md) for setup instructions.

#### [monitoring]

**klipper_exporter** - Enable Prometheus metrics exporter for Klipper
Expand Down Expand Up @@ -194,6 +201,10 @@ ssh: false
# VPN provider for remote access: none, tailscale
# Must SSH and run "tailscale up" to complete login flow
vpn: none
# Cloud: none, octoeverywhere
# - none - No cloud services enabled.
# - octoeverywhere - OctoEverywhere.com remote access
cloud: none

[monitoring]
# Enable Klipper Prometheus exporter on specified address
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ Heavily expanded firmware with extensive features and customization. Includes al
- Moonraker Adaptive Mesh Support - Object processing for adaptive mesh features
- Moonraker Apprise Notifications - Send print notifications to Discord, Telegram, Slack, and 90+ services
- [Timelapse Recovery Tool](https://github.com/horzadome/snapmaker-u1-timelapse-recovery) - Recover unplayable timelapse videos
- [OctoEverywhere](cloud.md) - Cloud-based remote access service for 3D printers

## Support

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ ssh: false
# VPN provider for remote access: none, tailscale
# Must SSH and run "tailscale up" to complete login flow
vpn: none
# Cloud: none, octoeverywhere
# - none - No cloud services enabled.
# - octoeverywhere - OctoEverywhere.com cloud-based remote access service
cloud: none

[monitoring]
# Enable Klipper Prometheus exporter on specified address
Expand Down
74 changes: 74 additions & 0 deletions overlays/firmware-extended/23-cloud/root/etc/init.d/S99cloud
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/bin/sh

OCTOEVERYWHERE_DAEMON="/usr/local/sbin/octoeverywhered"
OCTOEVERYWHERE_PIDFILE="/var/run/octoeverywhere.pid"
OCTOEVERYWHERE_LOGFILE="/home/lava/printer_data/logs/octoeverywhere.log"
OCTOEVERYWHERE_STATE_DIR="/home/lava/printer_data/octoeverywhere-store"

# Load config from user
EXTENDED_CFG="/home/lava/printer_data/config/extended/extended2.cfg"
CLOUD_PROVIDER=$(/usr/local/bin/extended-config.py get "$EXTENDED_CFG" remote_access cloud none)

start_octoeverywhere() {
if [ -f "$OCTOEVERYWHERE_PIDFILE" ] && kill -0 "$(cat "$OCTOEVERYWHERE_PIDFILE")" 2>/dev/null; then
echo "moonraker_octoeverywhere already running"
return 0
fi

printf "Starting moonraker_octoeverywhere: "
mkdir -p "$OCTOEVERYWHERE_STATE_DIR"
mv "$OCTOEVERYWHERE_LOGFILE" "$OCTOEVERYWHERE_LOGFILE.old"

start-stop-daemon -S -b -m -u lava \
-p "$OCTOEVERYWHERE_PIDFILE" \
-x "$OCTOEVERYWHERE_DAEMON"

echo "OK"
}

start() {
case "$CLOUD_PROVIDER" in
octoeverywhere)
start_octoeverywhere
;;
*)
echo "No cloud is enabled in the extended configuration, not starting any cloud service."
exit 0
;;
esac
}

stop() {
# Stop all cloud services, if any are running.
printf "Stopping OctoEverywhere: "
if [ -f "$OCTOEVERYWHERE_PIDFILE" ]; then
start-stop-daemon -K -p "$OCTOEVERYWHERE_PIDFILE" -s TERM
rm -f "$OCTOEVERYWHERE_PIDFILE"
echo "OK"
else
echo "not running"
fi
}

case "$1" in
start)
start
;;

stop)
stop
;;

restart|reload)
stop
sleep 1
start
;;

*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac

exit $?
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#!/bin/bash

#
# OctoEverywhere package manager
# Downloads and installs a pinned version of OctoEverywhere from GitHub
#

VERSION="4.6.6"
URL="https://github.com/QuinnDamerell/OctoPrint-OctoEverywhere/archive/refs/tags/${VERSION}.zip"
SHA256="8fedea60d50adc5763269cec47a46d81e534ea0066b790176fc819abea1b8db5"

# These paths are referenced in the init.d script
APP_DIR="/oem/apps/octoeverywhere"

check() {
if [[ -d "$APP_DIR/latest" ]]; then
echo "OctoEverywhere is installed."
return 0
else
echo "OctoEverywhere is not installed."
return 1
fi
}

download() {
rm -rf "$APP_DIR"
mkdir -p "$APP_DIR"

echo "Downloading OctoEverywhere ${VERSION} From GitHub..."
if ! /usr/local/bin/curl -sfSL -o "$APP_DIR/octoeverywhere.zip" "$URL"; then
echo "Download failed"
return 1
fi

echo "Verifying SHA256 checksum..."
ACTUAL_SHA256=$(sha256sum "$APP_DIR/octoeverywhere.zip" | awk '{print $1}')
if [[ "$ACTUAL_SHA256" != "$SHA256" ]]; then
echo "SHA256 mismatch!"
echo " Expected: $SHA256"
echo " Actual: $ACTUAL_SHA256"
return 1
fi
echo "Checksum verified."

echo "Extracting..."
if ! unzip -q "$APP_DIR/octoeverywhere.zip" -d "$APP_DIR"; then
echo "Extraction failed"
return 1
fi
echo "Extraction successful."

rm -rf "$APP_DIR/octoeverywhere.zip"

echo "Setting up Python virtual environment (this can take up to 60 seconds)..."
if ! python3 -m venv "$APP_DIR/venv"; then
echo "Failed to create virtual environment"
return 1
fi

echo "Installing dependencies (this can also take a bit)..."
if ! "$APP_DIR/venv/bin/pip" install --disable-pip-version-check -r "$APP_DIR/OctoPrint-OctoEverywhere-${VERSION}/requirements.txt"; then
echo "Failed to install dependencies"
return 1
fi

echo "Trying to install the optional zstdstandard package for better performance..."
if ! "$APP_DIR/venv/bin/pip" install --disable-pip-version-check zstandard; then
echo "Failed to install zstandard, continuing without it."
fi

# GitHub archives extract to OctoPrint-OctoEverywhere-<tag>
ln -s "OctoPrint-OctoEverywhere-${VERSION}" "$APP_DIR/latest"
echo "OctoEverywhere installed successfully to $APP_DIR"
}

case "$1" in
check)
check
;;
download)
if check; then
echo "OctoEverywhere is already installed."
exit 0
fi
if ! download; then
rm -rf "$APP_DIR"
exit 1
fi
;;
update)
echo "Updating OctoEverywhere..."
if ! download; then
rm -rf "$APP_DIR"
exit 1
fi
;;
clean)
echo "Removing OctoEverywhere installation..."
rm -rf "$APP_DIR"
echo "Removed."
;;
*)
echo "Usage: $0 check|download|update|clean"
exit 1
;;
esac
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/bash

DIR="/oem/apps/octoeverywhere/latest"
PIDFILE="/var/run/octoeverywhere.pid"
PYTHON="/oem/apps/octoeverywhere/venv/bin/python3"
STATE_DIR="/home/lava/printer_data/octoeverywhere-store"

if [[ ! -e "$PYTHON" ]]; then
echo "Error: Python interpreter not found at $PYTHON"
exit 1
fi

if [[ ! -e "$DIR" ]]; then
echo "Error: OctoEverywhere daemon not found at $DAEMON"
exit 1
fi

if [[ ! -e "$STATE_DIR" ]]; then
echo "Error: State directory not found at $STATE_DIR"
exit 1
fi

config_json() {
Comment thread
paxx12 marked this conversation as resolved.
cat <<"EOF"
{
"ConfigFolder": "/home/lava/printer_data/config",
"LogFolder": "/home/lava/printer_data/logs",
"LocalFileStoragePath": "/home/lava/printer_data/octoeverywhere-store",
"ServiceName": "octoeverywhere",
"VirtualEnvPath": "/oem/apps/octoeverywhere/venv",
"RepoRootFolder": "/oem/apps/octoeverywhere/latest",
"IsCompanion": false,
"MoonrakerConfigFile": "/home/lava/printer_data/config/moonraker.conf"
}
EOF
}

mkdir -p "$STATE_DIR"

# Tune malloc for embedded systems, so PY doesn't each so much memory.
export MALLOC_TRIM_THRESHOLD_=65536
export MALLOC_ARENA_MAX=2
export PYTHONPATH="$DIR:$PYTHONPATH"

exec "$PYTHON" -m moonraker_octoeverywhere "$(base64 <<< $(config_json))"
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
settings:
remote_access:
label: Remote Access
items:
cloud:
label: Cloud Access (Experimental)
get_cmd:
- /usr/local/bin/extended-config.py
- get
- /home/lava/printer_data/config/extended/extended2.cfg
- remote_access
- cloud
- none
options:
none:
label: None
cmd:
- bash
- -xc
- |
/usr/local/bin/extended-config.py add /home/lava/printer_data/config/extended/extended2.cfg remote_access cloud none &&
/etc/init.d/S99cloud stop
/usr/local/bin/octoeverywhere-pkg clean
octoeverywhere:
label: OctoEverywhere
cmd:
- bash
- -ec
- |
echo "WARNING: OctoEverywhere support is experimental. Higher resource usage may affect print quality."
sleep 5

echo ">> Downloading OctoEverywhere package..."
/usr/local/bin/octoeverywhere-pkg download

echo ">> Enabling OctoEverywhere..."
/usr/local/bin/extended-config.py add /home/lava/printer_data/config/extended/extended2.cfg remote_access cloud octoeverywhere

echo ">> Restarting OctoEverywhere service..."
/etc/init.d/S99cloud restart

echo
echo "OctoEverywhere enabled. Please wait a moment or check the logs for the account linking URL."
echo "If you need help, follow this guide:"
echo "https://octoeverywhere.com/s/snapmaker-u1"
echo "Contact Support: https://octoeverywhere.com/support"
echo

for i in {1..15}; do
echo ">> Looking for authorization URL in logs... ($i)"
if MATCH=$(grep -C 20 "This Plugin Isn't Connected To OctoEverywhere!" /home/lava/printer_data/logs/octoeverywhere.log); then
sed -n 's/.*WARNING //p' <<< "$MATCH"
exit 0
fi
sleep 1
done

echo "Authorization URL not found in logs. Please check the logs for more details."
default: none
Loading