diff --git a/lib/towerops_web/components/layouts.ex b/lib/towerops_web/components/layouts.ex index c3826c81..1da8a5e1 100644 --- a/lib/towerops_web/components/layouts.ex +++ b/lib/towerops_web/components/layouts.ex @@ -211,6 +211,12 @@ defmodule ToweropsWeb.Layouts do > Agents + <.nav_link + navigate={~p"/help"} + active={@active_page == "help"} + > + Help + diff --git a/lib/towerops_web/live/agent_live/index.html.heex b/lib/towerops_web/live/agent_live/index.html.heex index 827f6f51..f73c79ac 100644 --- a/lib/towerops_web/live/agent_live/index.html.heex +++ b/lib/towerops_web/live/agent_live/index.html.heex @@ -495,7 +495,7 @@
<.button phx-click="close_token_modal" variant="primary"> - I've Saved the Token + Close
diff --git a/lib/towerops_web/live/help_live/index.ex b/lib/towerops_web/live/help_live/index.ex new file mode 100644 index 00000000..f9041fde --- /dev/null +++ b/lib/towerops_web/live/help_live/index.ex @@ -0,0 +1,538 @@ +defmodule ToweropsWeb.HelpLive.Index do + @moduledoc false + use ToweropsWeb, :live_view + + alias Towerops.Accounts + alias Towerops.Organizations + + @impl true + def mount(_params, session, socket) do + # Check if user is logged in via session + current_user = get_current_user(socket, session) + is_authenticated = !is_nil(current_user) + + # Load user's default organization if authenticated + current_organization = + if current_user do + case Organizations.list_user_organizations(current_user.id) do + [first_org | _] -> first_org + [] -> nil + end + end + + # Build current_scope if authenticated + current_scope = + if current_user do + %{ + user: current_user, + impersonating?: false + } + end + + socket = + socket + |> assign(:page_title, "Help") + |> assign(:current_user, current_user) + |> assign(:is_authenticated, is_authenticated) + |> assign(:current_scope, current_scope) + |> assign(:current_organization, current_organization) + |> assign(:timezone, if(current_user, do: current_user.timezone, else: "UTC")) + + {:ok, socket} + end + + @impl true + def handle_params(params, _url, socket) do + section = Map.get(params, "section", "getting-started") + {:noreply, assign(socket, active_section: section)} + end + + defp get_current_user(socket, session) do + # Try to get current_user from socket assigns (if already set by on_mount) + with nil <- Map.get(socket.assigns, :current_user), + token when not is_nil(token) <- session["user_token"], + {user, _authenticated_at} <- Accounts.get_user_by_session_token(token) do + user + else + %Towerops.Accounts.User{} = user -> user + _ -> nil + end + end + + slot :inner_block, required: true + + defp code(assigns) do + ~H""" + + {render_slot(@inner_block)} + + """ + end + + attr :active_section, :string, required: true + + defp help_content(assigns) do + ~H""" +
+
+

Help & Documentation

+

+ Learn how to use Towerops to monitor your network infrastructure +

+
+ +
+ +
+ +
+ +
+
+ <%= case @active_section do %> + <% "getting-started" -> %> +
+

+ Getting Started with Towerops +

+ +
+

+ Towerops is a network monitoring platform that helps you keep track of your network devices, + monitor their health, and get alerts when issues occur. +

+ +

+ Quick Start Guide +

+ +
+ +
+
+
+ 1 +
+
+
+

+ Create a Site +

+

+ Sites represent physical or logical locations where your network devices are located. + Start by creating a site for your office, data center, or any location where you have equipment. +

+

+ Navigate to + <.code>Sites + → + <.code>Add Site +

+
+
+ + +
+
+
+ 2 +
+
+
+

+ Add Your First Device +

+

+ Add network devices like routers, switches, access points, or servers. You'll need the device's + IP address or hostname, and SNMP community string (for SNMP-enabled devices). +

+

+ Navigate to + <.code>Devices + → + <.code>Add Device +

+
+
+ + +
+
+
+ 3 +
+
+
+

+ View Device Metrics +

+

+ Click on any device to view real-time metrics including CPU usage, memory, temperature, + interface traffic, and more. Explore the different tabs to see network topology, port status, + and historical performance data. +

+
+
+
+ +
+
+ <.icon + name="hero-light-bulb" + class="h-5 w-5 text-blue-600 dark:text-blue-400 flex-shrink-0 mt-0.5" + /> +
+

+ Pro Tip +

+

+ For devices behind firewalls or in remote locations, you can deploy a remote poller + to monitor devices locally without exposing them to the internet. See the + <.link + patch={~p"/help?section=agents"} + class="underline hover:text-blue-900 dark:hover:text-blue-200" + > + Remote Pollers + + section for more information. +

+
+
+
+
+
+ <% "cloud-pollers" -> %> +
+

+ Cloud Pollers +

+ +
+

+ If you have publicly reachable devices, they will be automatically polled from one of our cloud pollers unless overridden by your settings. + Our cloud infrastructure monitors your devices without requiring any additional setup or agent installation. +

+ +

+ Active Cloud Pollers +

+ +
+ + + + + + + + + + + + + + + +
+ Location + + IPv4 Address + + IPv6 Address +
+ DFW (Dallas-Fort Worth) + + 144.202.64.79 + + 2001:19f0:6401:0af2:5400:05ff:fee7:1bfb +
+
+ +
+
+ <.icon + name="hero-information-circle" + class="h-5 w-5 text-blue-600 dark:text-blue-400 flex-shrink-0 mt-0.5" + /> +
+

+ Firewall Configuration +

+

+ If your devices are behind a firewall, make sure to allow SNMP traffic (UDP port 161) and ICMP (for ping monitoring) from these IP addresses. + For devices not accessible from the public internet, consider using a + <.link + patch={~p"/help?section=agents"} + class="underline hover:text-blue-900 dark:hover:text-blue-200" + > + Remote Poller + + instead. +

+
+
+
+
+
+ <% "agents" -> %> +
+

+ Remote Pollers +

+ +
+

+ Remote pollers allow you to monitor devices that are not accessible from the public internet, + such as devices behind firewalls, in private networks, or at remote locations. A remote poller + runs on your network and securely communicates with Towerops to poll your devices locally. +

+ +

+ Requirements +

+ +

+ Remote pollers can run on any system that supports Docker Compose, including: +

+ +
    +
  • Linux servers (Ubuntu, Debian, CentOS, RHEL, etc.)
  • +
  • Windows Server with Docker Desktop
  • +
  • macOS with Docker Desktop
  • +
  • Raspberry Pi or other ARM-based systems
  • +
  • Virtual machines (VMware, Hyper-V, Proxmox, etc.)
  • +
+ +
+

+ Minimum requirements: + 1 CPU core, 512 MB RAM, and network access to your devices +

+
+ +

+ Getting Started +

+ +
+ +
+
+
+ 1 +
+
+
+

+ Create an Agent Token +

+

+ Navigate to the + <.code>Agents + page in Towerops and create a new agent token. This token authenticates your remote poller with the Towerops platform. +

+
+
+ + +
+
+
+ 2 +
+
+
+

+ Get Docker Compose Configuration +

+

+ On the Agents page, add a new remote agent. Copy the + <.code>docker-compose.yml + file contents from the agent details, which includes your authentication token pre-configured. +

+
+
+ + +
+
+
+ 3 +
+
+
+

+ Deploy the Remote Poller +

+

+ Transfer the + <.code>docker-compose.yml + file to your server and run: +

+
+ docker compose up -d +
+

+ The remote poller will start automatically and connect to Towerops. +

+
+
+ + +
+
+
+ 4 +
+
+
+

+ Assign Devices to Remote Poller +

+

+ You can assign devices to your remote poller in several ways: +

+
    +
  • + Per Organization: + Set a default agent for all devices in your organization +
  • +
  • + Per Site: + Set a default agent for all devices at a specific site +
  • +
  • + Per Device: + Select the remote poller when creating or editing individual devices +
  • +
+

+ Devices assigned to a remote poller will be monitored from your local network instead + of from the cloud. +

+
+
+
+ +
+
+ <.icon + name="hero-shield-check" + class="h-5 w-5 text-blue-600 dark:text-blue-400 flex-shrink-0 mt-0.5" + /> +
+

+ Security Note +

+

+ Remote pollers use secure WebSocket connections to communicate with Towerops. + Your agent token is encrypted and should be kept confidential. The remote poller + only needs outbound HTTPS access (port 443) to connect to Towerops - no inbound + ports need to be opened on your firewall. +

+
+
+
+ +

+ Managing Remote Pollers +

+ +

+ You can view the status of your remote pollers on the Agents page. The page shows: +

+ +
    +
  • Last connection time
  • +
  • Number of devices assigned to each poller
  • +
  • Connection status (online/offline)
  • +
+ +
+
+ <.icon + name="hero-exclamation-triangle" + class="h-5 w-5 text-yellow-600 dark:text-yellow-400 flex-shrink-0 mt-0.5" + /> +
+

+ Important +

+

+ If a remote poller goes offline, devices assigned to it will not be monitored until + the poller comes back online. Consider setting up monitoring alerts for your remote + pollers to be notified if they disconnect. +

+
+
+
+
+
+ <% _ -> %> +
+

+ Section Not Found +

+

+ The requested help section could not be found. +

+
+ <% end %> +
+
+
+
+ """ + end +end diff --git a/lib/towerops_web/live/help_live/index.html.heex b/lib/towerops_web/live/help_live/index.html.heex new file mode 100644 index 00000000..b0c3c6f3 --- /dev/null +++ b/lib/towerops_web/live/help_live/index.html.heex @@ -0,0 +1,17 @@ +<%= if @is_authenticated do %> + + <.help_content active_section={@active_section} /> + +<% else %> + +
+ <.help_content active_section={@active_section} /> +
+
+<% end %> diff --git a/lib/towerops_web/router.ex b/lib/towerops_web/router.ex index 9517b104..a391c4e0 100644 --- a/lib/towerops_web/router.ex +++ b/lib/towerops_web/router.ex @@ -45,6 +45,7 @@ defmodule ToweropsWeb.Router do get "/", PageController, :home get "/privacy", PageController, :privacy get "/docs/api", ApiDocsController, :index + live "/help", HelpLive.Index, :index end # Agent communication via WebSocket channel at /socket/agent diff --git a/priv/static/changelog.txt b/priv/static/changelog.txt index 01aaf9a7..956f6d80 100644 --- a/priv/static/changelog.txt +++ b/priv/static/changelog.txt @@ -1,4 +1,5 @@ 2025-01-26 * Cloud poller improvements * Accessability improved +* Added initial help documentation