net/cloudflared: new plugin for Cloudflare Tunnel integration#5429
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new net/cloudflared plugin to integrate Cloudflare Tunnel (cloudflared) into OPNsense as a managed service with a native MVC UI and backend/service wiring, relying on the FreeBSD cloudflared package for the binary.
Changes:
- Introduces MVC pages + API endpoints to configure, control, and display tunnel/log status.
- Adds configd actions, templates, and scripts to generate config, apply tunables, and expose tunnel health.
- Adds firewall hook + watchdog (cron) for protocol-specific outbound rules and crash recovery.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Adds the new plugin to the repository plugin list. |
| net/cloudflared/Makefile | Declares the plugin and its dependency on cloudflared. |
| net/cloudflared/pkg-descr | Describes the plugin’s purpose and major features. |
| net/cloudflared/LICENSE | Adds plugin license file. |
| net/cloudflared/src/opnsense/service/templates/OPNsense/Cloudflared/+TARGETS | Installs generated templates to rc.conf.d, config.yml, and sysctl.d. |
| net/cloudflared/src/opnsense/service/templates/OPNsense/Cloudflared/rc.conf.d | Generates rc.conf.d service enablement + token env wiring. |
| net/cloudflared/src/opnsense/service/templates/OPNsense/Cloudflared/config.yml | Generates cloudflared config (metrics, protocol, flags). |
| net/cloudflared/src/opnsense/service/templates/OPNsense/Cloudflared/tunables.conf | Generates sysctl tunables for QUIC performance. |
| net/cloudflared/src/opnsense/service/conf/actions.d/actions_cloudflared.conf | Defines configd actions (start/stop/restart/status/reconfigure/log/tunnel_status). |
| net/cloudflared/src/opnsense/scripts/OPNsense/Cloudflared/reconfigure.sh | Reloads templates, applies sysctls, restarts service, reloads firewall. |
| net/cloudflared/src/opnsense/scripts/OPNsense/Cloudflared/tunnel_status.sh | Computes tunnel health via metrics + log cross-check. |
| net/cloudflared/src/opnsense/scripts/OPNsense/Cloudflared/monitor.sh | Watchdog script to restart the service when it dies unexpectedly. |
| net/cloudflared/src/opnsense/mvc/app/views/OPNsense/Cloudflared/index.volt | Adds UI for settings, service controls, health badge, and log viewer. |
| net/cloudflared/src/opnsense/mvc/app/models/OPNsense/Cloudflared/Menu/Menu.xml | Adds Services menu entry for the plugin UI. |
| net/cloudflared/src/opnsense/mvc/app/models/OPNsense/Cloudflared/ACL/ACL.xml | Adds ACL for UI/API endpoints. |
| net/cloudflared/src/opnsense/mvc/app/models/OPNsense/Cloudflared/Cloudflared.xml | Defines plugin configuration model (enabled/token/protocol/tunables). |
| net/cloudflared/src/opnsense/mvc/app/models/OPNsense/Cloudflared/Cloudflared.php | Adds BaseModel class for the plugin model. |
| net/cloudflared/src/opnsense/mvc/app/controllers/OPNsense/Cloudflared/IndexController.php | Serves the main UI page and general form. |
| net/cloudflared/src/opnsense/mvc/app/controllers/OPNsense/Cloudflared/forms/general.xml | Defines UI fields (token, protocol, tunables, flags). |
| net/cloudflared/src/opnsense/mvc/app/controllers/OPNsense/Cloudflared/Api/SettingsController.php | Exposes settings get/set API for the model. |
| net/cloudflared/src/opnsense/mvc/app/controllers/OPNsense/Cloudflared/Api/ServiceController.php | Exposes service actions plus tunnel status/log APIs. |
| net/cloudflared/src/etc/inc/plugins.inc.d/cloudflared.inc | Adds firewall hook, WAN-IP hook behavior, and service registration. |
| net/cloudflared/src/etc/cron.d/cloudflared | Adds a per-minute cron job to run the watchdog script. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
I did not intend to invoke Copilot to review that, automatic Github settings at work. It did identify a couple of useful things (bad links) which I fixed in f99ed31 below that I hadn't caught in my code review, and one comment on the cronjob - followed convention I saw in other plugins, but happy to tidy up the header comments if appropriate. |
|
I would suggest you remove as much cruft as possible and turn this into a minimum viable product first. I'm sure it could be 30-40% less code than this when using modern examples (e.g. the plugin I referenced). I work with AI every day, and this output here looks too random and overdesigned at quite a few spots. I don't know why the AI made those decisions, but better prompting and better examples should improve the output by a lot. Also keep in mind that you will be the owner of the end result and you will need to maintain this and give support for it. |
|
Understood. Leave it with me, I'll rebuild it clean by hand, and do my research properly. While it works, it can be a lot slimmer, and I'll take the comments on-board. Worth closing this PR for now and I'll recreate with a much tidier version? I leant a bit too hard on Claude, and I'm still learning the ropes with LLM code generation vs just writing it myself. Appreciate the feedback, I'm on it. |
|
You can leave this open, it helps to track the review progress and the actual changes you implement to improve it. No rush with anything. |
42e2ba8 to
3a6cb1c
Compare
|
Reimplemented from scratch with the advice from the comments above, based on the existing plugin architecture and reusing whatever components I could. Still having some issues around testing MultiWAN, but I happy to make ongoing improvements once I've got my install into production and can do live testing in a real environment. I've prepped initial basic documentation here - https://github.com/insanityinside/opnsense-docs/blob/net/cloudflared/source/manual/how-tos/cloudflared.rst - ready to merge in if this plugin gets approved, and will sort translation submissions too. Still used Claude to do the heavy lifting, but with a much tighter spec this time, and the code looks sane. Did manually set the process to "cloudflared" on the logs (as the logfile doesn't contain a process name in /var/log/cloudflared.log), but otherwise it's entirely using the vanilla logging setup now. |
12aa4f9 to
4a94664
Compare
|
@Monviech @fichtner Does this plugin need any further work before it gets merged, other than the net/cloudflared package being build on the opnsense repo? Seems to be running solidly on my live OPNsense server now, and has been stripped down to the absolute basics. Let me know if it needs any further changes, and I'll take care of them. I'm happy to maintain the plugin going forwards. |
|
Sorry there is not much time lately but we will circle back eventually. From what I can see the plugin looks reasonable, though we have to give this another look first (especially if the port builds without problems as well) |
|
Understood, just making sure I'd not missed anything required from me. Am happy if it's on the to-do list, completely understand resource constraints. I'll get the updated translations prepped and request access to the relevant translation projects to upload them. Hopefully shouldn't be any issues with the upstream package/port, has minimal requirements for build (lang/go125), and ca_root_nss as a runtime dependency (already being built and deployed on pkg.opnsense.org). |
Monviech
left a comment
There was a problem hiding this comment.
Just a few more comments. This looks quite clean already. Nice work so far.
| function cloudflared_configure() | ||
| { | ||
| return [ | ||
| 'newwanip' => ['cloudflared_configure_newwanip'], |
There was a problem hiding this comment.
Still not sure why we would need that.
There was a problem hiding this comment.
That's the recovery mechanism if the daemon died on startup if it couldn't resolve DNS, should cleanly pick it back up, as mentioned in #5429 (comment)
|
Also you need a PR here to add the cloudflared binary to the build. https://github.com/opnsense/tools/blob/master/config/26.1/ports.conf |
Wraps the net/cloudflared FreeBSD port to manage the cloudflared daemon via the standard OPNsense service control interface. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Completed the final changes. Let me do a full QA run against it on my router to make sure we've not broken anything and to ensure everything works as expected, then I can check my documentation and translations and make sure we're ready to go. Will update once I've completed testing. |
fichtner
left a comment
There was a problem hiding this comment.
looks good now
one note is that if you need pre-start routines for chmod or anything you can do a cloudflared_setup=setup.sh trick with rc. You can see that in use in a lot of other plugins and core features.
Only thought was to protect the token in the file - but if a user has access to shell on the box anyway, there's not a huge point to securing it further I don't think. Welcome any feedback on that one though. |
|
as long as the service doesn't throw warnings it's ok. we don't recommend/allow giving shell access to anything but full administrators anyway. |
bda9c59 to
6102c41
Compare
6102c41 to
e8c32a6
Compare
|
Only last thing I think I'll do is remove the restart cronjob completely - it's unnecessary, once it's running it's solid - will commit that, then we're good to merge. |
|
Happy with this now, testing passed, good to merge. Docs look good to merge - https://github.com/insanityinside/opnsense-docs/blob/net/cloudflared/source/manual/how-tos/cloudflared.rst - PR at opnsense/docs#887 - let me know any feedback/improvements needed. Will get set up for machine translations for the plugin. |
|
Merged, thanks! |
I'll approve your request now but it will take 2 months until the translations will be regenerated. This is a tedious process we only find the time to do 1-2 times a year. |
|
PS: Oh, it would make more sense to pick a language or leave it for others to translate. This is an unusual request. |
Ah, I was trying to be helpful - I'm used to generating appropriate translations and uploading them, and then having users tweak if they have a better version. I figured something was better than nothing. I looked at the build process on https://github.com/opnsense/lang, I can spin up a build box locally if it'd help, or I can leave it alone and let you do your usual processes 🙂 I've got the machine translation files if they're helpful for each language on poeditor.com, but I assume the strings would need gathering into en_US.pot first, by whatever means. |
Important notices
Before you submit a pull request, we ask you kindly to acknowledge the following:
If AI was used, please disclose:
Describe the problem
OPNsense has no native interface for managing Cloudflare Tunnel (cloudflared). Users behind CGNAT — where a publicly reachable WAN IP is not available — commonly use Cloudflare Tunnel as a supported, production-grade solution for exposing services without port forwarding. Managing it currently requires manual CLI setup with no OPNsense service integration.
Describe the proposed solution
Adds a new plugin
net/cloudflaredthat integrates Cloudflare Tunnel into OPNsense as a first-class service. This is an extensive rework of #5406 (original authorship and credit: @AlanMartines), which this PR builds on and supersedes. It is revised to address the architectural feedback from that review, and integrates my real-world experience with the net/cloudflared port on native FreeBSD.Key architectural change from #5406:
The original PR bundled a custom binary installer that downloaded cloudflared from a third-party GitHub fork. This plugin instead declares
PLUGIN_DEPENDS= cloudflared, delegating binary management entirely to pkg via the FreeBSD ports tree. The plugin is a pure configuration wrapper, as requested in the review of the original PR.net/cloudflaredwould need adding to the OPNsense port builds as it is not currently present in the repo (I manually installed the pre-built FreeBSD binary package for testing). I'm assuming it's not an automatic process with that PLUGIN_DEPENDS line.Functionality carried from the original PR:
Enhancements added in this rework:
Translations:
Machine-assisted translations for 20 languages, including original pt-BR translations from #5406, are prepared and ready to be contributed to the OPNsense lang repo via POEditor as a follow-up to this PR. I'm assuming that's the correct way to handle the translated strings for the plugin, please correct me if not.
Testing:
Tested on OPNsense 26.1.7 / FreeBSD 14.x (amd64).
Related issue
Closes #5070