Moongate logo # Moongate ### One app. Your Klipper printer. Anywhere. [![Latest release](https://img.shields.io/github/v/release/PEEKYPAUL/Moongate?label=latest%20release&color=6C63FF)](https://github.com/PEEKYPAUL/Moongate/releases/latest) [![License](https://img.shields.io/badge/license-PolyForm%20Noncommercial-blue)](LICENSE) [![Platform](https://img.shields.io/badge/platform-iPhone%20%7C%20Android-6C63FF)](#quick-start) [![App Store](https://img.shields.io/badge/iPhone-on%20the%20App%20Store-0D96F6?logo=apple&logoColor=white)](https://apps.apple.com/gb/app/moongate-klipper-control/id6785038887) [![Google Play](https://img.shields.io/badge/Android-on%20Google%20Play-34A853?logo=googleplay&logoColor=white)](https://play.google.com/store/apps/details?id=com.moongate.app.moongate) [![Website](https://img.shields.io/badge/website-peekypaul.github.io%2FMoongate-6C63FF)](https://peekypaul.github.io/Moongate/) Moongate on iPhone and Android - fleet dashboard with per-printer console and file tools, the full Mainsail UI in-app, and printing straight from stored G-code Free, source-available **iPhone and Android** control for your **Klipper 3D printer** - live webcam, print controls, temperatures, and the complete Mainsail/Fluidd UI - over home WiFi and **automatically over the internet** when you're away. Zero setup, no port forwarding, no subscriptions. **Prefer your own infrastructure? Run it your way.** The cloud-free **Direct (LAN/VPN)** mode talks straight to your printer over your network - or your own **WireGuard / Tailscale VPN** when you're out - and never touches the internet. [See how the two modes compare ›](#run-it-your-way) Download on the App Store Get it on Google Play Download the APK - early access channel **📱 Now on both stores.** Moongate is live on the [App Store](https://apps.apple.com/gb/app/moongate-klipper-control/id6785038887) and [Google Play](https://play.google.com/store/apps/details?id=com.moongate.app.moongate), built from one codebase. The stores carry the **stable releases**; the [GitHub APK](https://github.com/PEEKYPAUL/Moongate/releases/latest) is the **early-access channel** - every release lands there first, and it updates itself in-app.
--- ## Contents - [Features](#features) - [Screenshots](#screenshots) - [Quick start](#quick-start) - [Run it your way](#run-it-your-way) - [How it works](#how-it-works) - [Documentation](#documentation) - [Buy me a coffee](#buy-me-a-coffee) - [License](#license) --- ## Features - **Fleet dashboard** - every printer on one screen: live webcam, progress and time left, temperatures (hold the chamber reading to pick which sensor it shows), status. Sort by activity or drag your own order. - **Single-printer dashboard** - one printer full screen: camera, job, temperatures, macros, console, files and live X Y Z. Arrows step through your printers. - **Full Mainsail / Fluidd** - tap a tile for the complete web UI, kept loaded so it opens instantly, even over the tunnel. - **Home and away, automatically** - home WiFi first, the secure tunnel when you're out. No port forwarding, no setup. - **Direct (LAN/VPN) mode** - cloud-free: the app talks straight to Moonraker, and away from home over your own WireGuard or Tailscale. [Compare the two modes ›](#run-it-your-way) - **Print controls** - pause, resume, stop, firmware restart, a double-tap emergency stop, and a power button for printers with a power device or power macro. - **Control panel** - arrange temperature, motion and macro modules per printer, and turn any Klipper macro into a labelled button. - **Console and config editor** - a live G-code console with command completions, and a Klipper-aware `printer.cfg` editor with a backup and one-tap restore. - **Print from the printer** - browse the G-code already on it, with slicer thumbnails, and start a print. No re-upload. - **Print queue** - line up stored files, see what is up next on the tile, and start or pause the queue, without opening Mainsail. - **G-code layer viewer** - open any stored file as a 3D layer stack you spin with a finger, coloured like Orca's preview: temperature, flow rate, layer time, speed, fan speed, or the filament colours of a multi-material print with a key per tool (and, on an MMU, a switch to what is loaded in the gates right now), layer by layer, then start the print from there, or save the file to your phone. - **Cameras** - Mainsail cameras auto-detected, go2rtc included; add an external IP camera; full-screen view with pinch-to-zoom; switch between several on one printer. - **Multi-toolhead** - IDEX and tool changers show every hotend as its own chip, active tool highlighted, preheat for all at once. - **Notifications** - opt-in start / finish / pause / error alerts with the reason, live progress in the shade, heat-soak and "cool enough to remove" alerts, and a `MOONGATE_NOTIFY` macro for your own gcode. - **Lighting** - a bulb on the tile drives your light macros and shows the real on/off state. - **App lock** - PIN or biometric, auto-lock, screenshot protection. Off by default. - **Themes and layout** - light, dark or custom colours and background, Material You on Android, a 36-font picker, 1-3 columns, landscape. - **9 languages** - English, German, French, Spanish, Italian, Chinese, Russian, Polish and Brazilian Portuguese. - **Backup and restore** - move to a new phone and your printers come back with no re-pairing. - **In-app updates** - the early-access APK updates itself, and a tile badge updates the printer's plugin from your phone. - **Guided tour** - an optional walkthrough that points out each part of the app on your first printer. - **Hardened remote access** - every internet request needs a short-lived signed token; a leaked tunnel URL gives an attacker only `401`s. [How it works ›](#how-it-works) Every feature in depth, with the version it arrived in: **[Feature guide ›](docs/features.md)** --- ## Screenshots
The Single-printer dashboard - one printer full screen with the camera, the print job, temperatures, the tool buttons and live X Y Z Secure LAN pairing Menu
Icon guide - what every dashboard icon means Custom theme editor G-code layer viewer - a stored file as a 3D layer stack, coloured by fan speed with Orca's ramp, with the layer rail and a Start print button
Per-printer G-code console - history pre-filled, quick-command chips File System - browse the printer's configuration folder Structured printer.cfg editor - names fixed, values editable, backup before the first change

Print notifications in the Android notification shade
Optional print notifications - live fleet status & start / finish / error alerts, right in your notification shade.
--- ## Quick start Three steps: install the Pi plugin, install the app, pair. ### 1. Install the Pi plugin SSH into your Pi and run: ```bash curl -fsSL https://raw.githubusercontent.com/PEEKYPAUL/Moongate/master/klipper-plugin/install.sh | bash ``` The installer asks how your phone will connect: **1) Moongate cloud** (the default - remote access from anywhere) or **2) Direct (LAN/VPN)** (cloud-free; [see how the two compare](#run-it-your-way)). With the default it installs the plugin, the `MOONGATE_PAIR` macro, the QR pairing page, the auth proxy, and the Cloudflare tunnel, then restarts Moonraker. Future updates appear in **Mainsail → Software Updates → Moongate**. > **Using a 3rd-party printer instead?** (e.g. an Elegoo Centauri Carbon on OpenCentauri COSMOS) - this installer targets Raspberry-Pi-style machines and won't run on embedded vendor firmware. Follow [3rd-party printer support](docs/third-party-printers.md) instead: a one-file install, no installer needed.
Requirements & custom HTTP port
**Requirements:** a Raspberry Pi running Klipper + Moonraker + Mainsail or Fluidd (standard KIAUH / MainsailOS / FluiddPI). Tested on aarch64 (Pi 4/5) and armv7l (Pi 3). **Non-standard port?** Moonraker usually serves on port 80 (the installer's default). If yours is elsewhere, tell the installer: ```bash MOONGATE_PORT=8080 bash -c "$(curl -fsSL https://raw.githubusercontent.com/PEEKYPAUL/Moongate/master/klipper-plugin/install.sh)" ``` In the app's pair screen, set the **Port** field to match (leave it blank for 80). **Other things talk to Moonraker at this Pi's IP?** A cloud install moves Moonraker onto localhost so only Moongate's gated tunnel is exposed. An on-Pi client like KlipperScreen then needs pointing at `127.0.0.1`, and a central "farm" Mainsail/Fluidd on another machine should target port 80 (this Pi's nginx serves the full Moonraker API there) - see [Troubleshooting](TROUBLESHOOTING.md) for both. If something genuinely needs raw `:7125`, keep the bind exactly as it is: ```bash MOONGATE_KEEP_BIND=1 bash -c "$(curl -fsSL https://raw.githubusercontent.com/PEEKYPAUL/Moongate/master/klipper-plugin/install.sh)" ``` **LAN-only (own VPN, no tunnel)?** If you reach your printer over your own VPN / WireGuard and don't want an outbound Cloudflare tunnel or external exposure, install in LAN-only mode. It keeps Moonraker on the LAN (`0.0.0.0`) and skips cloudflared, the auth proxy, and the tunnel service. The plugin, `MOONGATE_PAIR` macro, and mDNS advertisement are still installed, and a later cloud re-install enables remote access. **The installer asks.** Run it interactively (the normal `curl | bash` one-liner counts) and it offers the choice - answer `2` for Direct (LAN/VPN): ``` How will your phone connect to this printer? 1) Moongate cloud - remote access from anywhere (secure tunnel) 2) Direct (LAN/VPN) - home network / your own VPN only, no cloud ``` On a box that already runs LAN-only the default keeps it LAN-only, so pressing Enter never converts your mode. To preselect an answer and skip the question (scripts, headless installs): ```bash # LAN-only, piped MOONGATE_LAN_ONLY=1 bash -c "$(curl -fsSL https://raw.githubusercontent.com/PEEKYPAUL/Moongate/master/klipper-plugin/install.sh)" # LAN-only, from a local checkout bash install.sh --lan-only # cloud, never prompt (automation) MOONGATE_LAN_ONLY=0 bash -c "$(curl -fsSL https://raw.githubusercontent.com/PEEKYPAUL/Moongate/master/klipper-plugin/install.sh)" ``` Choosing LAN-only on a box that already has the tunnel stack retires it (disables the tunnel + auth proxy) and converges to LAN-only. In the app, add a LAN-only printer with **Add printer → Direct (LAN/VPN)** - scan the QR from `MOONGATE_PAIR` or type the printer's address. A LAN-only box can also be paired through the cloud as normal (while it has internet); Direct mode is for the fully cloud-free / internet-isolated case. Two networking notes: - **`trusted_clients` must cover your phone.** The app talks to Moonraker directly, so the phone's subnet needs to be in Moonraker's `[authorization] trusted_clients`. Home WiFi and WireGuard's usual `10.x` range typically already are; **Tailscale's `100.64.0.0/10` usually is not** - add it or Moonraker answers 401 before Moongate ever runs. - **Give the Pi a fixed address.** The app stores the address a Direct printer was added with, so use a DHCP reservation (or static IP) - if the Pi's IP changes you'd have to re-add it. Direct-mode printers work fully offline, but skip everything cloud-backed: no print notifications, and away from home the app only reaches them through your own VPN.
### 2. Install the app [![Download on the App Store](https://img.shields.io/badge/iPhone-App%20Store-0D96F6?style=for-the-badge&logo=apple&logoColor=white)](https://apps.apple.com/gb/app/moongate-klipper-control/id6785038887) [![Get it on Google Play](https://img.shields.io/badge/Android-Google%20Play-34A853?style=for-the-badge&logo=googleplay&logoColor=white)](https://play.google.com/store/apps/details?id=com.moongate.app.moongate) [![Download Moongate APK](https://img.shields.io/badge/%E2%AC%87%20APK-early%20access-6C63FF?style=for-the-badge&logo=android&logoColor=white)](https://github.com/PEEKYPAUL/Moongate/releases/latest) **iPhone** - get it on the [App Store](https://apps.apple.com/gb/app/moongate-klipper-control/id6785038887). **Android** - get it on [Google Play](https://play.google.com/store/apps/details?id=com.moongate.app.moongate) (recommended - stable releases, updated automatically by the store). **Android early access** - want each release the day it ships? Grab the APK from the [Releases page](https://github.com/PEEKYPAUL/Moongate/releases) instead: enable **Install from unknown sources** for your browser or file manager, then open the APK. From then on it updates itself in-app. It's signed with the same key as the Play build, so you can move between the two channels later without losing your printers. ### 3. Pair 1. Run **`MOONGATE_PAIR`** in the Klipper / Mainsail console. 2. On a device on the **same WiFi as your Pi**, open `http:///moongate-pair.html` - a QR appears. 3. In the app, tap **+ → Scan QR** and point the camera at it. Done - your printer lands on the dashboard. No working camera? Type the **`GATE-XXXX-XXXX`** code shown in the console instead. And if you opened the pair page on the phone the app is on, just **tap the link under the QR** (v0.9.59+) - the app opens straight into pairing. > **How quickly does it connect? Scanning the QR is instant.** > - ✅ **Scan the QR (recommended)** - an **instant local connection**: your printer is on the dashboard in about a second, because the QR hands the app your Pi's local address directly. Remote access over the secure tunnel keeps **building in the background** - you never wait on it. > - ⚠️ **GATE code** - there's no instant local hand-off, so the printer doesn't appear until the **Cloudflare tunnel** has finished building (that's what carries the connection). Usually under a minute - a little longer right after a Pi reboot. It isn't stuck; give it a moment, or scan the QR for an instant connection. > Pairing is LAN-only by design: nothing to port-forward, no URL to share. Reinstalling or switching phones? **Back up your config first** - restoring it brings your printers back online without re-pairing. See **[Updating & removing](docs/managing-moongate.md)**. --- ## Run it your way Moongate gives every printer a choice of two connections - and you can mix them freely on one dashboard. | | ☁️ Moongate cloud (default) | 🔌 Direct (LAN/VPN) | |---|---|---| | Setup | pair once with the QR / GATE code | pick **Direct** when the installer asks, add by QR or address | | Away from home | automatic - secure tunnel, zero config | through **your own VPN** (WireGuard, Tailscale) | | Print notifications | ✅ | ❌ (no cloud to send them) | | What touches the cloud | pairing, a heartbeat, short-lived tokens | **nothing - zero calls, ever** | | Needs internet | to pair and for the tunnel | **never - works fully offline** | | Best for | most people - it just works | VPN owners, isolated networks, zero-cloud setups | Switch an existing printer between modes anytime from its edit dialog - no re-pairing. If you later want a Direct printer on the cloud, re-run the installer normally and pair it; the app absorbs the old tile automatically. Networking notes for Direct mode (Moonraker's `trusted_clients`, give the Pi a fixed address) are in the [LAN-only install section](#quick-start) above. Direct mode isn't picky about the host, either: from plugin 0.6.17 it needs **zero extra Python packages**, so machines that were never a Raspberry Pi - embedded boards, vendor printers on community firmware - can join the dashboard with a one-file install. See [3rd-party printer support](docs/third-party-printers.md). --- ## How it works
Moongate's two connection routes: route 1, Moongate cloud - the app gets a short-lived signed token from the access broker and reaches the Raspberry Pi over the LAN at home or through Cloudflare's tunnel away, with the Pi's auth proxy admitting only broker-signed requests so a leaked tunnel URL returns only 401s; route 2, Direct - the app talks straight to Moonraker over home WiFi or the user's own WireGuard/Tailscale VPN, gated by trusted_clients, with zero cloud involvement.
**Route 1 - Moongate cloud.** Your Pi runs Klipper, Moonraker, the Moongate plugin, and an **auth proxy** that gates everything reachable from the internet. A minimal **access broker** handles anonymous sign-in (no email, no password) and tracks the current tunnel URL; the app fetches a fresh signed token before each request and tries home WiFi first, then the tunnel. **The headline:** leaking the tunnel URL alone gives an attacker nothing - every path through it returns `401` without revealing what's underneath. Full threat model in [SECURITY.md](SECURITY.md); code-level detail in [ARCHITECTURE.md](ARCHITECTURE.md). **Route 2 - Direct (LAN/VPN).** No broker, no tunnel, no heartbeats: the app talks straight to Moonraker on your network - or across your own VPN - gated by Moonraker's `trusted_clients`, exactly like Mainsail in a desktop browser. The Pi makes **zero outbound calls** and the whole thing works with no internet at all. --- ## Documentation | Document | What's inside | |---|---| | [Moongate website](https://peekypaul.github.io/Moongate/) | The features, screenshots and setup steps on one page - the friendliest place to send someone new | | [Feature guide](docs/features.md) | Every feature in depth, with the version it arrived in and the plugin it needs | | [Updating & removing](docs/managing-moongate.md) | Updating the app & plugin, reinstalling / moving to a new phone, full uninstall | | [3rd-party printer support](docs/third-party-printers.md) | Direct (LAN/VPN) mode on non-Pi hosts - the one-file install, supported machines, VPN notes | | [DEVELOPMENT.md](DEVELOPMENT.md) | Building from source, repo layout, debugging, release signing, CI | | [ARCHITECTURE.md](ARCHITECTURE.md) | Code structure, state management, data-flow walkthroughs, design decisions | | [SECURITY.md](SECURITY.md) | Threat model, what the tunnel does and doesn't expose, the empirical verification, vulnerability reporting | | [TROUBLESHOOTING.md](TROUBLESHOOTING.md) | Common failure modes - offline tiles, tunnel issues, pairing failures - each with copy-paste diagnostics | | [CHANGELOG.md](CHANGELOG.md) | Every release as a few short bullets: what is new, what was fixed | | [Privacy policy](https://peekypaul.github.io/Moongate/privacy-policy.html) | What data the app handles and why - anonymous, no analytics, no tracking, no data sold | > **Building from source?** `cd mobile && flutter pub get && flutter build apk --release --flavor github --dart-define=MOONGATE_CHANNEL=github`. Full developer workflow in [DEVELOPMENT.md](DEVELOPMENT.md). --- ## Buy me a coffee Moongate is free, source available, and built in my spare time for the Klipper community - no ads, no subscriptions, no data harvesting. If it's earned a spot on your phone, you can buy me a coffee on [Ko-fi](https://ko-fi.com/peekypaul) (or tip via PayPal) to say thanks. Every contribution goes straight back into the project: test hardware, the cloud service that keeps remote access working, and the time to keep shipping features. Thank you for being part of it 💜

Buy me a coffee on Ko-fi Donate with PayPal

--- ## License **PolyForm Noncommercial License 1.0.0** - see [LICENSE](LICENSE) for the full text. - ✅ Free to read, build, self-host, modify, and share for **non-commercial** use - including charities, schools, and public / research / government institutions. - ❌ Selling Moongate, charging for access, or bundling it in a paid product needs a **separate written licence**. Want to use Moongate commercially? [Open an issue](https://github.com/PEEKYPAUL/Moongate/issues/new) or contact [@PEEKYPAUL](https://github.com/PEEKYPAUL) to discuss terms. ---
Created by Paul Sharman