Skip to content

Added plugin bitbang#1443

Merged
jneilliii merged 11 commits into
OctoPrint:gh-pagesfrom
richlegrand:add-bitbang
Jul 1, 2026
Merged

Added plugin bitbang#1443
jneilliii merged 11 commits into
OctoPrint:gh-pagesfrom
richlegrand:add-bitbang

Conversation

@richlegrand

Copy link
Copy Markdown
Contributor
  • [x ] You have read the "Registering a new Plugin" guide.
  • You want to and are able to maintain the plugin you are registering, long-term.
  • You understand why the plugin you are registering works.
  • You have read and acknowledge the Code of Conduct.

What is the name of your plugin?

OctoPrint-BitBang

What does your plugin do?

Provides full remote access to an OctoPrint instance -- including live H.264 video -- over a single secure HTTPS shareable link. It uses BitBang to broker a WebRTC peer-to-peer connection, so no account, subscription, port forwarding, tunnel or VPN is required. Video is hardware-encoded on Pi 4 (V4L2 M2M) and software-encoded on Pi 5 / other Linux hosts. Integrates with OctoPrint's WebcamProviderPlugin for snapshots and timelapse.

Where can we find the source code of your plugin?

https://github.com/richlegrand/OctoPrint-BitBang

Was any kind of genAI (ChatGPT, Copilot etc) involved in creating this plugin?

Yes -- some assistance for refactoring. Plugin is not vibe-coded; I designed it and can maintain it. BitBang is where much of the code is and it is fully written by me.

Is your plugin commercial in nature?

No

Does your plugin rely on some cloud services?

Yes -- the bitba.ng signaling service brokers the WebRTC peer connection. Once peers are connected, all media and HTTP traffic flows directly between the browser and OctoPrint over an encrypted WebRTC channel (DTLS-SRTP); bitba.ng only sees the public key, a derived UID, and connection metadata. If a direct peer-to-peer path can't be established, bitba.ng may relay the encrypted stream via TURN — even then, the relay sees ciphertext only. No account, no telemetry. Privacy policy: https://github.com/richlegrand/OctoPrint-BitBang/blob/main/PRIVACY.md

Further notes

The cloud attribute is declared in the registration YAML; __plugin_privacypolicy__ is set in the plugin source and points at the same policy URL.

Comment thread _plugins/bitbang.md Outdated
@github-project-automation github-project-automation Bot moved this to In Progress in OctoPrint Backlog May 25, 2026
@jneilliii

Copy link
Copy Markdown
Contributor

I'd recommend including instructions for OctoPi installs (majority use case for OctoPrint) on how to disable the webcam stream services...I have similar instructions in my go2rtc gist for reference.

https://gist.github.com/jneilliii/93b412cb0bbf6b7bfd76f7e10d612f24?permalink_comment_id=4993013#gistcomment-4993013

@jneilliii

Copy link
Copy Markdown
Contributor

One other thing I just remembered is that you might want to add your plugin_identifier to the list of plugins for remote access.

https://github.com/OctoPrint/plugins.octoprint.org/blob/gh-pages/_topics/remote_access.md

@richlegrand

richlegrand commented May 26, 2026

Copy link
Copy Markdown
Contributor Author

One other thing I just remembered is that you might want to add your plugin_identifier to the list of plugins for remote access.

Just added -- thanks :)
And I added instructions for stopping stream services to the BitBang README.md.

@richlegrand richlegrand requested a review from jneilliii May 28, 2026 02:26

@jneilliii jneilliii left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one small correction needed for this PR noted in remote_access.md.

relative to the plugin itself, just a quick scan with octoscanner brings up a couple of security concerns relative to the use of BlueprintPlugin.csrf_exempt.

+---------------------------------------------------- OctoScanner ----------------------------------------------------+
|                                                                                                                     |
| +- Plugin OctoPrint-BitBang --------------------------------------------------------------------------------------+ |
| | +---------------------------------------- Summary (2 total findings) -----------------------------------------+ | |
| | | 2 security                                                                                                  | | |
| | +-------------------------------------------------------------------------------------------------------------+ | |
| | +------------------------------------------- Security (2 findings) -------------------------------------------+ | |
| | | SEC-0006                                                                                                    | | |
| | | Endpoint exempted from CSRF protection via BlueprintPlugin.csrf_exempt(). Ensure that the exemption is      | | |
| | | necessary and that the endpoint uses an alternative anti-CSRF mechanism (e.g. token in header).             | | |
| | | File: octoprint_bitbang\__init__.py:155                                                                     | | |
| | |      154 |         @octoprint.plugin.BlueprintPlugin.route("/offer", methods=["POST"])                      | | |
| | |   >  155 |         @octoprint.plugin.BlueprintPlugin.csrf_exempt()                                          | | |
| | |      156 |         def local_offer(self):                                                                   | | |
| | | Suggestion: Remove the decorator if not strictly required. Otherwise, document why the endpoint cannot use  | | |
| | | CSRF protection and ensure another anti-CSRF mechanism is in place.                                         | | |
| | |                                                                                                             | | |
| | | SEC-0006                                                                                                    | | |
| | | Endpoint exempted from CSRF protection via BlueprintPlugin.csrf_exempt(). Ensure that the exemption is      | | |
| | | necessary and that the endpoint uses an alternative anti-CSRF mechanism (e.g. token in header).             | | |
| | | File: octoprint_bitbang\__init__.py:250                                                                     | | |
| | |      249 |         @octoprint.plugin.BlueprintPlugin.route("/camera/brightness", methods=["POST"])          | | |
| | |   >  250 |         @octoprint.plugin.BlueprintPlugin.csrf_exempt()                                          | | |
| | |      251 |         def set_brightness(self):                                                                | | |
| | | Suggestion: Remove the decorator if not strictly required. Otherwise, document why the endpoint cannot use  | | |
| | | CSRF protection and ensure another anti-CSRF mechanism is in place.                                         | | |
| | +-------------------------------------------------------------------------------------------------------------+ | |
| +-----------------------------------------------------------------------------------------------------------------+ |
|                                                                                                                     |
| +--------------------------- Rule Statistics (1 rules matched 2 times on 1/1 plugins) ----------------------------+ |
| | Matches  Rule ID   Message                                                                                      | |
| |       2  SEC-0006  Endpoint exempted from CSRF protection via BlueprintPlugin.csrf_exempt(). Ensure that the    | |
| |                    exemption is necessary and that the endpoint uses an alternative anti-CSRF mechanism (e.g.   | |
| |                    token in header).                                                                            | |
| +-----------------------------------------------------------------------------------------------------------------+ |
|                                                                                                                     |
+---------------------------------------------------------------------------------------------------------------------+

Comment thread _topics/remote_access.md Outdated
@jneilliii

Copy link
Copy Markdown
Contributor

I'm also not 100% sure why, but I've installed this plugin on 3 different instances and it only actually loads the settings/navbar in 1. I initially thought it was because of the pi zero 2w not being supported, but it also didn't load on my pi 4 with USB camera attached. The working install I don't have a camera attached to it but remote access did work fine. Would appreciate some more eyes on this plugin review due to the nature of it being remote access.

@richlegrand

Copy link
Copy Markdown
Contributor Author

I'm also not 100% sure why, but I've installed this plugin on 3 different instances and it only actually loads the settings/navbar in 1.

Hi jneilliii,
To try to decouple things, if it doesn't show up in the navbar, please look in settings -> plugins -> bitbang. The URL should be listed there also. If you try the URL and appears good, it's good info for tracking down the issue.

thanks!
--rich

@richlegrand

Copy link
Copy Markdown
Contributor Author

relative to the plugin itself, just a quick scan with octoscanner brings up a couple of security concerns relative to the use of BlueprintPlugin.csrf_exempt.

CSRF exemptions removed in v0.1.3; the JS now reads csrf_token from the cookie and sends it as X-CSRF-Token. Re-scan should be clean. It might require a hard reload.

thanks!

@richlegrand richlegrand requested a review from jneilliii May 28, 2026 13:07
@jneilliii

Copy link
Copy Markdown
Contributor

I'm also not 100% sure why, but I've installed this plugin on 3 different instances and it only actually loads the settings/navbar in 1.

Hi jneilliii, To try to decouple things, if it doesn't show up in the navbar, please look in settings -> plugins -> bitbang. The URL should be listed there also. If you try the URL and appears good, it's good info for tracking down the issue.

thanks! --rich

That was the weird part, there were no UI elements loading, not even settings, although the plugin was shown as being installed in plugin manager. I attempted reinstall and force refresh of the page. What I did notice was that the instances that did not work, the restart of OctoPrint was not triggered like it should have been.

@jneilliii

Copy link
Copy Markdown
Contributor

the JS now reads csrf_token from the cookie and sends it as X-CSRF-Token

I think it would be better served to use the OctoPrintClient.getRequestHeaders function available in the OctoPrint js client rather than messing with the cookies directly. Alternatively, I think you could use the get/post methods of the OctoPrint js client instead of fetch and those headers will be added for you automatically (would need verification of that).

@richlegrand

Copy link
Copy Markdown
Contributor Author

Hi jneilliii,
Switched to OctoPrint.getRequestHeaders per your suggestion. Verified against client/base.js:194-230 -- that path also adds X-Api-Key for API-key callers, which is a nice bonus. Pushed in v0.1.4.

@richlegrand

Copy link
Copy Markdown
Contributor Author

I just posted v0.1.5:

  • CSRF: switched to OctoPrint.getRequestHeaders per your suggestion. Verified against client/base.js:194-230 -- that path also adds X-Api-Key for API-key callers
  • Plugin loads on 1 of 3 instances: tracked the silent disappearance to a bare except ImportError: pass at the bottom of init.py that was swallowing any load failure (intended for standalone-CLI use but too broad). Now logs the failure to octoprint.log. Also replaced the print() calls in octoprint_adapter.py with the plugin logger, so camera-open failures land in
    the same place instead of stdout/journald.

When you have a moment to re-test on a failing instance, the log line to look for is "BitBang plugin not loaded: " -- that should name the missing dependency directly. Happy to dig in from there.

Thanks for the thoughtful review.

@jacopotediosi jacopotediosi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@richlegrand Thanks for the contribution! I finally found some spare time to review the plugin; my findings are below.

  1. In setup.py, you should pass license="MIT" to setuptools.setup() for compatibility with setuptools<77, as shown in the OctoPrint cookiecutter template.
  2. In pyproject.toml the following dependencies are never used and can be removed: numpy, Pillow, aiohttp.
  3. I don't think it's necessary to override several plugin attributes in __init__.y, e.g. __plugin_version__, since the plugin version is already declared in pyproject.toml. I'd suggest minimizing unnecessary overrides to reduce the risk of forgetting to update the value in both places.
  4. In both templates you do some weird JavaScript things, like fetching /api/settings. The correct approach is to use the viewmodels provided by OctoPrint, knockout bindings, and template vars.

In addition, I wanted to check how the PIN verification was done, but I couldn't because it seems to happen inside bitbangproxy, which however is included in the python library bitbang only as a precompiled binary. Is there a reason why the proxy's source code is not available?

@jacopotediosi

Copy link
Copy Markdown
Member

Errata corrige: it appears that the PIN is checked by the two binaries contained in the bin folder of the plugin. Are sources available for them too?

@richlegrand

Copy link
Copy Markdown
Contributor Author

Ah, sorry! I took a detour with the code and it's in transition. I was thinking that no one was looking, and I've just been checking into main. Please give me a a few days and I'll give an "all clear" :) I'll address your findings also-- many thanks for those.  

The previous code was all python and it had some speed issues running on the Pi 3, so I decided to do the proxy over the Go binary (bitbangproxy, which isn't public yet).  This code will be fully open source as well. 
The development of this has taken a lot more time than anticipated, but I'm excited to say that it runs really well with the Go code. And it works well on 32-bit OS (quick note to @jneilliii) I'll be doing some more QA on 32 and 64 bit OS before asking you for another look.
 
thanks!

@jacopotediosi

Copy link
Copy Markdown
Member

Gotcha, so just two quick suggestions about Python and Go interactions.

I'd suggest avoiding the use of subprocessing and looking into whether they can interact through bindings (Foreign Function Interface) instead. For example, you can do this by compiling Go as a C shared library and calling it from Python with ctypes or cffi. You might also want to take a look at gopy.

Regarding compilation, I'd suggest keeping only the Go source code in the repository instead of the compiled binaries, and adding a GitHub Action (or similar) that compiles them and bundles them into the Python library's build artifact.

@richlegrand

Copy link
Copy Markdown
Contributor Author

Hi @jacopotediosi and @jneilliii -- thanks for your patience while I finished the rework. I just tagged v0.2.1, which should close out the open items. Here's the "all clear" :)

The Go proxy is now fully open source. What was the private bitbangproxy is public: https://github.com/richlegrand/bitbang-cli (MIT). The PIN check and all signaling/transport logic are in the source there.

Binaries are no longer committed -- they're built from source in CI. Per @jacopotediosi's suggestion, the octoprint_bitbang/bin/ binaries are now gitignored and out of the repo. A GitHub Action (publish.yml) checks out the bitbang-cli source, cross-compiles the arm64 + armv7 proxy (CGO_ENABLED=0, statically linked), bundles them into the wheel, and asserts they're present before publishing to PyPI -- so the shipped binary is reproducible from public source.

Some notes on FFI vs. subprocess -- I looked into ctypes/cffi and gopy. I ended up keeping the subprocess boundary on purpose: the proxy is a long-lived process running its own WebRTC/networking event loop, and I wanted hard crash-isolation from the OctoPrint process plus a clean lifecycle (it's the same binary users can run standalone as bitbang). Folding a cgo network event loop into the Python process-- GIL/threading interaction, shared-memory failure modes-- felt like more risk than the subprocess gives up, especially for remote-access code; the FD/socketpair handoff keeps the IPC surface small. Happy to revisit, but that was the reasoning.

bare except ImportError: pass at the bottom of __init__.py that was silently swallowing load failures (fixed in v0.1.5 --it now logs "BitBang plugin not loaded: "). That also explains the missing auto-restart younoticed: the import was failing before the plugin registered. v0.2.1 keeps the explicit logging, so a re-test on a previously-failing pi should name the cause directly-- happy to chase it from there.

Remote-access security posture-- since you wanted more eyes given the nature of the plugin: traffic is peer-to-peer WebRTC/DTLS (end-to-end encrypted; the signaling server only brokers the handshake, and a TURN relay (if one is needed) carries ciphertext only), there's an optional PIN, no account, and the earlier CSRF exemptions are gone (now via OctoPrint.getRequestHeaders). A fresh octoscanner run should come back clean.

I've QA'd on both 32-bit and 64-bit OctoPi. Please take look when you have a moment-- thanks!

@jneilliii

Copy link
Copy Markdown
Contributor

I'm testing out your new instructions on my failed instances, but then realized something about your plugin that should be modified. The DOM replacement of the default classic webcam is not the way to go for webcam providers. Instead, you should generate your own webcam jinja2 template. This way you aren't stepping on the toes of other plugins like the classic webcam and providing your own. An example of this can be found in the simple https://github.com/OctoPrint/OctoPrint-Testpicture

@richlegrand

Copy link
Copy Markdown
Contributor Author

you should generate your own webcam jinja2 template

I made this modification to v0.2.3.

@jneilliii

Copy link
Copy Markdown
Contributor

So after getting through the fixes for bookworm install of aiortc as described here the plugin is functional, but I wonder if there would be a better approach for initial install given the CI based binary changes. The install now requires a PyPi based install of OctoPrint-BitBang to be fully functional (after doing the other system level prerequisites) instead of a source distribution zip URL. The only other approach I can think of is bundling the compiled binaries into a source+binaries release asset zip on GitHub rather than pushing to PyPi. I know the WS281x plugin does this, albeit without the compiled binaries part.

That being said, I think the plugin listing should include a prerequisites section documenting the necessary steps prior to attempting install of the plugin as you have on the PyPi description until either @jacopotediosi or @foosel are able to chime in on possible alternatives.

@richlegrand

Copy link
Copy Markdown
Contributor Author

I didn't realize the registry installs from a zip archive, not pip/PyPI. That reframes it-- thanks for the nudge and the WS281x pointer.

Happy to make the change-- I'll have CI bundle the proxy binaries into a release.zip attached to the GitHub release, and point the listing's archive: at releases/latest/download/release.zip. I'll also add a prerequisites section covering the system-level steps. PyPI stays available for anyone who prefers pip install (but I could remove if it's confusing -- let me know)

I'll try to get this set up today before travel. Let me know if there's anything else.

@jneilliii

Copy link
Copy Markdown
Contributor

If you go the release zip route make sure to update the software update hook as well.

@foosel

foosel commented Jun 11, 2026

Copy link
Copy Markdown
Member

I'm currently quite busy with 2.0.0rc3 and some other stuff in the background of OctoPrint, so I cannot look closer at the discussion here, but just to clarify:

I didn't realize the registry installs from a zip archive, not pip/PyPI.

This basically just depends on how you register your plugin & your software update hook. In theory it should also work perfectly fine to set a PyPI package name as the archive URL. However, if you provide/stay with the default of the GitHub branch zip, it will go with that and not whatever you might or might not also have uploaded to PyPI.

Check the docs on the pypi_release check type.. you'd basically go with something like

plugin_id:
  type: pypi_release
  package: your_package
  pip: "your_package=={target_version}"

for the software update hook, and have just your_package as the archive URL on the plugin repo.

That should work. However, I have to admit that this would make your plugin the first plugin to ever test this, and also remove the option to support release channels further down the road (those require github releases/branches).

If you need to support multiple architectures though with your combined bits, this is probably the best way to go, and at some point this really should also be tested.

@jneilliii

Copy link
Copy Markdown
Contributor

for the software update hook, and have just your_package as the archive URL on the plugin repo.

I thought that this might work that way, but wasn't completely sure since I don't remember any other plugins using this approach.

@jneilliii jneilliii left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all my concerns have been addressed. Will request re-review by @jacopotediosi.

@jneilliii jneilliii requested a review from jacopotediosi June 17, 2026 16:00
@richlegrand

Copy link
Copy Markdown
Contributor Author

quickie note -- I'm back from travel and I'm doing a refactor to address the code in bitbang_navbar.jinja2 that fetches /api/settings that @jacopotediosi brought up. I hope to have it up tonight :)

@richlegrand

Copy link
Copy Markdown
Contributor Author

@jacopotediosi @jneilliii -- all open items addressed, ready for another look:

  1. setup.py passes license="MIT"
  2. dropped unused deps (numpy, Pillow, aiohttp)
  3. version no longer duplicated-- init.py reads it from package metadata
  4. navbar + settings now use a Knockout viewmodel (settingsViewModel dep) -- no more fetch('/api/settings')

Proxy source has been public since v0.2.1 at bitbang-cli (PIN check + transport there; CI builds the binaries from it).

@jneilliii -- added the Prerequisites section and set the title to BitBang.

Thanks!

@richlegrand

Copy link
Copy Markdown
Contributor Author

Hi @jacopotediosi,

Cut v0.2.7 with the items from your earlier review:

  • CSRF: exemptions removed, proper token handling
  • Unused deps and duplicate code: dropped
  • Navbar/settings: Knockout viewmodels (no direct API calls)
  • Proxy source: published publicly
  • Prerequisites added; init-error logging improved

Smoke-tested locally on a Pi (clean install, clean boot, video bridge + signaling working end-to-end). Full QA pass on my side is still in progress, but everything you flagged is in this release and ready for re-verification whenever you have a chance.

thanks!

@jacopotediosi

Copy link
Copy Markdown
Member

Hi @richlegrand,
I'm a bit busy because I'm working on restoring an abandoned plugin. I'll review it as soon as possible, likely next week. Sorry for the inconvenience and thanks for your patience.

@richlegrand

richlegrand commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

Sorry for the inconvenience and thanks for your patience.

I appreciate the amount of work you guys have. Take your time and let me know if there's anything I can do to help.

@jacopotediosi

jacopotediosi commented Jun 22, 2026

Copy link
Copy Markdown
Member

Hi all, thanks for your patience.
I did another round of review; my considerations are below.

PIN hardening

The only secret preventing remote control of the OctoPrint instance - should the URL become known to an attacker (e.g. because it's visible during a screen share or a live stream on some social platform) or should the Signaling Server be compromised - is the PIN. It follows that the PIN is a fundamental authentication mechanism and must be secure. On this point, I have the following concerns:

  1. There is no minimum length or complexity requirement for the PIN; e.g. it's possible to set a PIN of just a single numeric digit. The only mention is in the plugin's README, which states 4+ digit, but this is not actually enforced. In any case, even 4+ digits is not something I would consider robust.
  2. There is no concrete incentive to push the user to set a PIN, which is empty (disabled) by default. I suggest implementing WizardPlugin to display a dialog prompting the user to set the PIN immediately after installing the plugin. I also suggest keeping the service disabled by default and requiring the user to enable it in the settings, since it doesn't seem like a good idea that connecting without a PIN is possible before the user has even had the opportunity to set one. It seems like a safer approach for the plugin's installation not to imply, in itself, that remote control is active right away.
  3. There are no rate-limiting or lockout mechanisms to prevent brute-forcing the PIN. Furthermore, there is no limit on the number of parallel connections, which can be used both to parallelize PIN brute-forcing and to perform DoS attacks. I think both these protective measures should be implemented in bitbang-cli.
  4. In bitbang-cli, the PIN verification is implemented using ==, which is not constant-time and therefore allows hypothetical timing-based attacks to guess the PIN one character at a time.

PIN Bypass

In addition to the above, a brief analysis with Claude uncovered a complete bypass of the PIN.

The HandleMessage function routes packets based on the StreamID:

  • Packets with StreamID 0 are routed to handleConnect, where the PIN is checked and s.authenticated is set only if the entered PIN is correct.
  • Packets with a StreamID other than 0 are routed to handleSYN and handleBody, which forward them to the OctoPrint instance.

handleSYN and handleBody do not check s.authenticated, which is only set by handleConnect and never read by anyone else. Therefore, by sending packets with a StreamID other than 0, the OctoPrint instance is reached directly, even without entering the PIN.

Claude also generated a short PoC for me, which I'm attaching: bitbang_pin_bypass.py.

Launching it with bitbang_pin_bypass.py 'https://bitba.ng/<UID>#<CODE>' opens a browser tab displaying the OctoPrint instance's login screen routed via bitba.ng without inserting the PIN even if it's set, confirming the vulnerability.

@jacopotediosi jacopotediosi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above

@richlegrand

Copy link
Copy Markdown
Contributor Author

@jacopotediosi thanks for the thoughtful review -- I have fixes for these, will hopefully have ready within the next day.

thanks

@richlegrand

Copy link
Copy Markdown
Contributor Author

@jacopotediosi -- thanks for the thorough review and the PoC, it made the bypass easy to verify against. All five findings are fixed and shipped in 0.2.8 (now the latest, so Plugin Manager pulls it). Since you have the exploit handy, the quickest confirmation is to re-run it against a fresh 0.2.8 install it now returns unauthenticated instead of reaching OctoPrint.

  • PIN bypass (StreamID != 0): every non-control frame is now gated on a completed connect/auth handshake; pre-auth streams are rejected and never reach OctoPrint. (gate, tests replay your exact sequence)
  • Non-constant-time compare: now subtle.ConstantTimeCompare over fixed-width SHA-256 digests (pin.go); hmac.compare_digest in the Python implementation.
  • No rate-limiting: 3-strike session teardown + a 2 s delay per failure + a concurrent-session cap.
  • PIN not required by default: fail-closed (no PIN --> no tunnel), plus a setup wizard that won't finish without a valid PIN or an explicit opt-out.
  • Min length: >= 4 characters, enforced server-side.

Enforcement lives in the proxy layer (which owns the WebRTC transport), not just the plugin. The Python device implementation was brought to parity too. Happy to walk through anything.

thanks

@jacopotediosi

jacopotediosi commented Jun 26, 2026

Copy link
Copy Markdown
Member

Sorry, I'm busy again, I'll review this one on June 29 or 30.

Assuming the above security remediations have been implemented correctly (will check them also, of course), I only have one remaining concern regarding the correctness of the reverse proxy headers, since for OctoPrint bitba.ng traffic arrives from 127.0.0.1 (I think) and I'm not sure exactly what security implications this could have (e.g., autologin, etc). For this reason I'll need to setup and check against real installations both with Octopi and without.

@richlegrand

Copy link
Copy Markdown
Contributor Author

Along those lines I added XFF headers to bitbang-cli (proxy), but didn't turn on. I'm guessing this would be something you would like to enable -- let me know.

@richlegrand

Copy link
Copy Markdown
Contributor Author

@jacopotediosi-- following up on the X-Forwarded-For point: as of 0.2.10 (latest), the proxy now forwards the real client IP by default, so OctoPrint sees the actual remote address instead of 127.0.0.1 -- autologinLocal no longer treats a remote visitor as local. (Verified that a remote login resolves to the external IP.) The only visible effect is OctoPrint's own "external access" banner.

Let me know your thoughts.

@jacopotediosi

Copy link
Copy Markdown
Member

@richlegrand in OctoPrint there is a page "Reverse Proxy Test" which shows if the headers are configured correctly. It should be reachable from the footer or the About page iirc. If you could post a screenshot of that, taken from Bitbang on a real OctoPi installation, that could certainly speed up my final review on Monday/Tuesday. Thanks :)

@richlegrand

Copy link
Copy Markdown
Contributor Author

I had to do some URL editing, but here's what I got:
Screenshot from 2026-06-28 14-50-12

@jacopotediosi jacopotediosi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jneilliii jneilliii merged commit 0007f7b into OctoPrint:gh-pages Jul 1, 2026
4 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in OctoPrint Backlog Jul 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants