Skip to content

runtime: route menu URLs through get_service_url for SWAG-aware modules#907

Closed
igorpecovnik wants to merge 27 commits into
mainfrom
runtime-menu-use-swag-urls
Closed

runtime: route menu URLs through get_service_url for SWAG-aware modules#907
igorpecovnik wants to merge 27 commits into
mainfrom
runtime-menu-use-swag-urls

Conversation

@igorpecovnik
Copy link
Copy Markdown
Member

Summary

config.runtime.sh writes the per-service info shown on each menu item's right column. Lines using a hardcoded http://$DISPLAY_URL:${module_options[…,port]} template kept showing the direct host:port even when the matching service was fronted by SWAG, so users saw e.g. Bazarr remove (http://test.armbian.com:6767) instead of the SWAG subfolder URL.

The get_service_url helper that powers TRA002 (transmission), IMM002 (immich), and NBOX02 (netbox) already does the right thing:

  • no SWAG running → http://$DISPLAY_URL:port
  • SWAG running but service-conf not enabled → http://$DISPLAY_URL:port
  • SWAG running and service-conf enabled → https://$DISPLAY_URL/<service>

This PR routes the remaining menu lines whose service has a matching stock proxy-conf in linuxserver/reverse-proxy-confs:master through that helper.

Pairs naturally with #906 (which enables the proxy-conf at install time): once a user installs a wired module on a host that runs SWAG, the menu reflects the SWAG path on the next refresh.

Switched (23 lines)

bazarr, deluge, domoticz, duplicati, embyserver → emby, filebrowser, ghost (path /ghost), grafana, homepage, jellyfin, lidarr, medusa, netdata, phpmyadmin, pi-hole → pihole (path /admin), plexmediaserver → plex, prowlarr, qbittorrent, radarr, readarr, sabnzbd, sonarr, syncthing.

Intentionally left untouched

  • NCT002 (nextcloud) and CPT002 (cockpit): the direct URL is HTTPS on a self-signed port; get_service_url's fallback returns http://… on hosts without SWAG, which would break those panels. Worth a follow-up that extends the helper with a fallback-protocol argument.
  • POR002 (portainer): already has its own explicit SWAG-aware branch right above this section; no change needed.
  • Modules whose service has no stock SWAG proxy-conf (actualbudget, adguardhome, octoprint, openhab, …): fallback would equal current behaviour but offer no upside, and routing through the helper would drag in a per-row exec into the SWAG container for nothing. Kept on the direct template.

Test plan

  • On a host without SWAG: menu items for the 23 switched services still show http://<host>:<port> exactly as before.
  • On a host with SWAG and the matching proxy-conf enabled (e.g. via software: auto-configure SWAG reverse proxy for all modules with stock proxy-confs #906): Bazarr remove (https://my.home.org/bazarr) instead of (http://my.home.org:6767).
  • pi-hole row still ends with /admin; ghost row still ends with /ghost.
  • No regression on the three rows that already used the helper (transmission, immich, netbox).

igorpecovnik and others added 27 commits May 9, 2026 19:44
Update module_swag.sh to follow current armbian-config patterns:

Changes:
- Replace direct dialog calls with wrapper functions (dialog_inputbox,
  dialog_passwordbox, dialog_yesno, dialog_msgbox, dialog_infobox)
- Add comprehensive error handling with user-friendly messages
- Make hostname change optional with confirmation dialog
- Add URL sanitization to remove protocol prefixes
- Add lsio network existence check before container creation
- Add container status check in password command
- Improve variable naming consistency (swag_* prefix)
- Add help text with web interface URL and documentation link
- Add success/info dialogs throughout the workflow
- Fix typos in variable names

Benefits:
- Better user experience with clear error messages
- More robust handling of edge cases
- Consistent with other software modules
- Prevents silent failures
- Provides actionable feedback when operations fail

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace lscr.io/linuxserver/* with linuxserver/* to use Docker Hub
instead of the LinuxServer.io registry, which resolves pull failures
when lscr.io is not accessible.

Root cause: lscr.io registry is not reachable from many networks,
causing "pull failed" errors during installation. Docker Hub
(docker.io/linuxserver/*) is more widely accessible and reliable.

Changed 20 modules:
- bazarr, code-server, deluge, duplicati, embyserver, jellyfin
- lidarr, mariadb, medusa, nextcloud, phpmyadmin, prowlarr
- qbittorrent, radarr, sabnzbd, sonarr, swag, syncthing
- transmission, wireguard

All modules now pull from linuxserver/* on Docker Hub which is
the canonical registry for LinuxServer.io images.

Fixes installation failures for users without lscr.io access.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix UX issues with dialog windows being too small:

- Increase all dialog box dimensions to prevent text cutoff
- Input boxes: 15x90 and 12x80 (was 10x80 and 10x70)
- Message boxes: 10-12x60-70 (was 8-10x50-60)
- Yes/No dialogs: 15x80 (was 12x70)
- Info boxes: 15x80 (was 10x70)

- Remove redundant success dialog between container creation
  and password setup to reduce click count
- Improve dialog titles for better clarity
- Enhance message wording throughout

Benefits:
- Windows properly sized for content
- One less click during installation
- Better user experience with readable dialogs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix 'unbuffer: command not found' error during Docker image pulls
by automatically installing the expect package when unbuffer is not available.

The unbuffer command (from expect package) is required for real-time
progress display during Docker image pulls via Docker API. This was
causing failures for users who didn't have expect installed.

Changes:
- Add unbuffer availability check in docker_operation_progress()
- Auto-install expect package via pkg_install if missing
- Ensures smooth Docker pull experience for all users

Fixes errors during image pulls in SWAG and other Docker modules.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix two issues reported during testing:

1. SSL certificates not working until manual container restart:
   - Add automatic restart after container creation
   - Wait up to 30 seconds for SSL certificate initialization
   - Show info dialog during certificate initialization
   - Store domain URL in config file for later use

2. Success messages showing IP instead of domain URL:
   - Store swag_url to /armbian/swag/config/.swag_url during install
   - Read stored URL in password command for display
   - Read stored URL in help command for display
   - Fallback to LOCALIPADD if stored URL not found

Changes:
- Container restart after installation for SSL certificate init
- URL storage/retrieval system for domain display
- All user-facing messages now show domain URL instead of IP
- 30-second wait for certificate initialization with progress dialog

Benefits:
- SSL certificates work immediately after installation
- Users see their actual domain in messages, not IP address
- Better UX with clear feedback during certificate init

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove lsio network creation/check code as this is already
handled by the Docker module during installation.

The Docker module ensures the lsio network exists, so individual
software modules don't need to duplicate this check.

Reduces code duplication and simplifies SWAG module.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Change from .swag_url (hidden file) to SWAG_URL (regular file) for
storing the domain URL configuration.

Changes:
- Store to SWAG_URL instead of .swag_url
- Use SWAG_URL globally across password, help, and status commands
- Fallback to LOCALIPADD only if SWAG_URL file doesn't exist
- Update comments to clarify global usage pattern

Benefits:
- Consistent naming with environment variable conventions (uppercase)
- Regular file instead of hidden file (easier to find and manage)
- Clear documentation of global URL configuration
- Replaces IP address detection with stored domain URL

This makes SWAG_URL the canonical source for the domain URL
throughout the module, replacing IP-based fallbacks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add global SWAG_URL variable that replaces LOCALIPADD in runtime menu
URLs when SWAG reverse proxy is installed with a domain.

Changes in module_env_init.sh:
- Read SWAG_URL from /armbian/swag/config/SWAG_URL if it exists
- SWAG_URL becomes a global variable available throughout armbian-config

Changes in config.runtime.sh:
- Add DISPLAY_URL variable that uses SWAG_URL if available,
  otherwise falls back to LOCALIPADD
- Replace all http:// and https:// with
   in menu URLs

Benefits:
- When SWAG is installed with a domain (e.g., example.com), all
  software menu URLs show the actual domain instead of local IP
- Users see https://example.com:port instead of https://192.168.1.100:port
- More professional and accurate for domain-based deployments
- Automatic fallback to IP when SWAG is not installed

This makes the entire software menu system domain-aware when
SWAG reverse proxy is configured.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add SWAG reverse proxy URL to the runtime menu configuration.

Changes:
- Add SWAG01 entry to WebHosting section
- Display https:// (uses SWAG domain or falls back to IP)
- SWAG shows in software menu with proper HTTPS URL

When SWAG is installed with a domain, users will see:
- https://example.com (if SWAG configured with example.com)
- https://192.168.1.100 (fallback to local IP if no SWAG domain)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Automatically configure SWAG reverse proxy for Transmission when:
- SWAG container is installed and running
- SWAG has built-in proxy config for transmission (transmission.subfolder.conf)
- Transmission container starts successfully

Flow:
1. Transmission is installed and starts
2. Check if SWAG container exists
3. Read SWAG domain from SWAG_URL file (fallback to IP)
4. Enable SWAG's built-in transmission.subfolder.conf proxy config
5. Reload SWAG nginx to apply the proxy
6. Show user the HTTPS URL with credentials

Result:
- Transmission accessible via: https://test.armbian.com/transmission
- Instead of: http://192.168.1.100:9091
- Uses SWAG's built-in proxy configuration (no custom config needed)
- SSL/HTTPS provided by SWAG Let's Encrypt certificates

This provides automatic secure access to Transmission through SWAG
reverse proxy with proper domain URLs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix the SWAG proxy configuration to use the global SWAG_URL variable
instead of reading from a file.

Changes:
- Remove file reading logic with problematic cat command
- Use global SWAG_URL variable (set in module_env_init.sh)
- Fallback to LOCALIPADD if SWAG_URL is not set

This is cleaner and more reliable, using the established global variable
pattern instead of file I/O.

Fixes cat errors during transmission installation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix SWAG reverse proxy configuration to handle SWAG's sample files.

SWAG provides proxy configs as .sample files that need to be copied
before use. Updated transmission module to:

1. Check for transmission.subfolder.conf.sample file
2. Copy sample to actual config (transmission.subfolder.conf) if needed
3. Enable the proxy by creating .enabled file
4. Reload nginx to apply changes

This fixes the issue where SWAG has sample configs but not actual configs.

Also created comprehensive diagnostic script for testing proxy setup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Update runtime config menu to display SWAG subfolder paths instead of
port numbers when SWAG reverse proxy is enabled for a service.

Changes:
- Add get_service_url() helper function that checks:
  * If SWAG is running
  * If SWAG proxy is enabled for the service
  * Returns appropriate URL format

- Update Transmission menu entry to use helper function:
  * With SWAG proxy: https://test.armbian.com/transmission
  * Without SWAG: http://192.168.1.100:9091

Logic:
1. SWAG not running → Show port (local access)
2. SWAG running, proxy disabled → Show port (local access)
3. SWAG running, proxy enabled → Show subfolder (HTTPS domain access)

This provides user-friendly menu URLs that reflect the actual access method.
Local installs remain port-based, SWAG-proxied installs show domain paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add service name to module_options so runtime config can determine
which services have SWAG proxy configurations available.

Changes:
- Add [module_transmission,servicename]=transmission to module_options
- Update config.runtime.sh to use module_options[module_transmission,servicename]
  instead of hardcoded transmission string

This provides a standardized way for modules to declare their SWAG proxy
service name, making it easier to:
- Identify which services have SWAG proxy support
- Add more services to SWAG proxy system
- Maintain consistency across modules

Pattern for other services:
1. Add [module_SERVICE,servicename]=servicename to module_options
2. Update config.runtime.sh to use
3. Ensure SWAG has corresponding proxy config file

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add docker_configure_swag_proxy() to module_docker_utils.sh
  * Takes servicename as parameter
  * Returns 0 on success, 1 on error, 2 when SWAG not available
  * Handles copying sample configs and enabling proxy automatically
- Update transmission module to use new function
  * Reduces code from 28 lines to 1 line
  * Makes SWAG configuration reusable for all modules

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add servicename module option
- Call docker_configure_swag_proxy() after container starts
- Homepage will be automatically accessible via SWAG reverse proxy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The TZ (timezone) variable is required for proper time display
in the Homepage dashboard. This matches the configuration used
in other modules like transmission, grafana, etc.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds HOMEPAGE_VAR_LOCALIPADD and HOMEPAGE_VAR_SWAG_URL environment
variables that can be used in Homepage YAML configuration files.

Usage in config files:
- http://{{HOMEPAGE_VAR_LOCALIPADD}}:9091
- https://{{HOMEPAGE_VAR_SWAG_URL}}/service

This prevents hardcoded localhost URLs in service configurations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add servicename module option
- Call docker_configure_swag_proxy() after container starts
- Portainer will be automatically accessible via SWAG reverse proxy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The SWAG proxy configuration files have hardcoded ports that need
to match the actual service ports. Updated the function to:

- Accept optional port parameter
- Edit the upstream_port in the nginx config using sed
- Pass correct ports from modules:
  * transmission: 9091
  * homepage: 3000 (internal port)
  * portainer: 9000

This fixes the issue where SWAG proxy was pointing to wrong ports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two issues were causing the 502 error:

1. Missing network: Portainer wasn't on the lsio Docker network,
   so SWAG couldn't reach it by container name

2. Wrong port/protocol: Portainer Web UI uses port 9443 with HTTPS,
   not port 9000 (which is for Edge agent)

Fixes:
- Added --net=lsio to Portainer docker run command
- Updated docker_configure_swag_proxy() to accept protocol parameter
- Changed Portainer proxy config to use port 9443 and https protocol

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two changes to fix Portainer URL in the menu:

1. config.runtime.sh: Updated Portainer menu URL to use HTTPS
   - With SWAG: https://SWAG_URL/portainer
   - Without SWAG: https://IP:9443 (not http://IP:9000)

2. module_portainer.sh: Changed port from 9000 to 9443
   - Port 9000 is the Edge Agent port (not main UI)
   - Port 9443 is the Web UI port that users actually access

This fixes the menu link to point to the correct Portainer Web UI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add servicename module option
- Call docker_configure_swag_proxy() with port 8080 (internal HTTP port)
- Update menu URL to use get_service_url function for proper SWAG support
- Netbox external port is 8222, internal port is 8080

When SWAG is enabled: https://SWAG_URL/netbox
Without SWAG: http://IP:8222

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add servicename module option
- Call docker_configure_swag_proxy() with port 8080 (internal HTTP port)
- Update menu URL to use get_service_url function for proper SWAG support
- Immich external port is 8077, internal port is 8080

When SWAG is enabled: https://SWAG_URL/immich
Without SWAG: http://IP:8077

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ules with stock proxy-confs

docker_configure_swag_proxy() in module_docker_utils.sh enables the
matching SWAG proxy-conf for a service by copying its
${name}.subfolder.conf.sample to .conf, optionally overriding port
and protocol, and reloading nginx. Until now it was only wired for 5
modules (homepage, immich, netbox, portainer, transmission), so users
running SWAG had to hand-enable every other proxied service.

Wire the call into the 22 software modules whose dockername matches a
proxy-conf shipped in linuxserver/reverse-proxy-confs:master:
  bazarr, deluge, domoticz, dozzle, duplicati, embyserver (=emby),
  filebrowser, ghost, grafana, jellyfin, lidarr, medusa, netdata,
  nextcloud (https), phpmyadmin, pi-hole (=pihole), prowlarr,
  qbittorrent, radarr, sabnzbd, sonarr, syncthing.

Each call passes the container's internal port; the function rewrites
upstream_port in the proxy-conf via sed before enabling. Nextcloud
also gets protocol=https because its container exposes 443/TLS.

The function silently no-ops (returns 1) if SWAG isn't installed or
the matching proxy-conf is missing — no behavioural change for users
who don't run SWAG. Modules without a stock SWAG proxy-conf
(actualbudget, adguardhome, armbianrouter, code-server, evcc,
hastebin, jellyseerr, mariadb, mysql, navidrome, netalertx, octoprint,
openhab, owncloud, postgres, prometheus, redis, stirling, unbound,
uptime-kuma, wallos, watchtower, wireguard) are intentionally not
wired — adding the call would just produce a silent no-op.
config.runtime.sh writes the per-service info shown on each menu
item's right column. Lines using a hardcoded
'http://$DISPLAY_URL:${module_options[…,port]}' template kept
showing the direct host:port even when the matching service was
fronted by SWAG, so users would see e.g. 'Bazarr remove
(http://test.armbian.com:6767)' instead of the SWAG path.

The get_service_url helper (added together with TRA002, IMM002, NBOX02
earlier) already does the right thing — http://$DISPLAY_URL:port when
SWAG isn't running or doesn't proxy the service, and
https://$DISPLAY_URL/<service> when the proxy-conf is enabled.
Switch the remaining menu lines whose service has a matching SWAG
proxy-conf in linuxserver/reverse-proxy-confs:master to use it.

Switched (23 lines):
  bazarr, deluge, domoticz, duplicati, embyserver→emby,
  filebrowser, ghost (path /ghost), grafana, homepage, jellyfin,
  lidarr, medusa, netdata, phpmyadmin, pi-hole→pihole (path /admin),
  plexmediaserver→plex, prowlarr, qbittorrent, radarr, readarr,
  sabnzbd, sonarr, syncthing.

Left untouched intentionally:
  - NCT002 (nextcloud) and CPT002 (cockpit): direct URL is
    https-only on a self-signed port; helper falls back to http on
    no-SWAG hosts which would be wrong. Worth a follow-up that
    extends the helper with a fallback-protocol arg.
  - POR002 (portainer): already has its own SWAG-aware branch.
  - Modules without a matching SWAG proxy-conf (actualbudget,
    adguardhome, etc.): fallback would equal current behaviour, but
    no upside either; keep the diff focused on actually-affected
    services.
@github-actions github-actions Bot added the 05 Milestone: Second quarter release label May 9, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 9, 2026

Warning

Rate limit exceeded

@igorpecovnik has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 31 minutes and 23 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 73738bea-31bd-44d6-9551-3f4d7daee1d4

📥 Commits

Reviewing files that changed from the base of the PR and between 5ded5c7 and 7b2df66.

📒 Files selected for processing (34)
  • tools/modules/functions/module_docker_utils.sh
  • tools/modules/functions/module_env_init.sh
  • tools/modules/runtime/config.runtime.sh
  • tools/modules/software/module_bazarr.sh
  • tools/modules/software/module_code-server.sh
  • tools/modules/software/module_deluge.sh
  • tools/modules/software/module_domoticz.sh
  • tools/modules/software/module_dozzle.sh
  • tools/modules/software/module_duplicati.sh
  • tools/modules/software/module_embyserver.sh
  • tools/modules/software/module_filebrowser.sh
  • tools/modules/software/module_ghost.sh
  • tools/modules/software/module_grafana.sh
  • tools/modules/software/module_homepage.sh
  • tools/modules/software/module_immich.sh
  • tools/modules/software/module_jellyfin.sh
  • tools/modules/software/module_lidarr.sh
  • tools/modules/software/module_mariadb.sh
  • tools/modules/software/module_medusa.sh
  • tools/modules/software/module_netbox.sh
  • tools/modules/software/module_netdata.sh
  • tools/modules/software/module_nextcloud.sh
  • tools/modules/software/module_phpmyadmin.sh
  • tools/modules/software/module_pi-hole.sh
  • tools/modules/software/module_portainer.sh
  • tools/modules/software/module_prowlarr.sh
  • tools/modules/software/module_qbittorrent.sh
  • tools/modules/software/module_radarr.sh
  • tools/modules/software/module_sabnzbd.sh
  • tools/modules/software/module_sonarr.sh
  • tools/modules/software/module_swag.sh
  • tools/modules/software/module_syncthing.sh
  • tools/modules/software/module_transmission.sh
  • tools/modules/software/module_wireguard.sh
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch runtime-menu-use-swag-urls

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the size/large PR with 250 lines or more label May 9, 2026
@igorpecovnik
Copy link
Copy Markdown
Member Author

Superseded — squashed into #906 alongside the per-module wiring.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

05 Milestone: Second quarter release size/large PR with 250 lines or more

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant