Skip to content

Instantly share code, notes, and snippets.

@seven1m
Last active October 23, 2025 18:51
Show Gist options
  • Select an option

  • Save seven1m/3689a08639fe2959b58ad84daad7c136 to your computer and use it in GitHub Desktop.

Select an option

Save seven1m/3689a08639fe2959b58ad84daad7c136 to your computer and use it in GitHub Desktop.
A stupid simple Ruby cgi script to connect/disconnect AllStarLink nodes, with favorites! (An alternative to allmon)
#!/usr/bin/env ruby
# WARNING: DO NOT EXPOSE THIS TO THE INTERNET. IT HAS NO SECURITY!
# WARNING: DO NOT EXPOSE THIS TO THE INTERNET. IT HAS NO SECURITY!
# WARNING: DO NOT EXPOSE THIS TO THE INTERNET. IT HAS NO SECURITY!
#
# FOR REAL: I mean it. This script doesn't do any validation of the commands,
# so some bad person could do more than just connect/disconnect stuff.
# They could inject anything into your system with this tool. I WARNED YOU.
#
# 1. Install Ruby:
#
# sudo apt-get install ruby
#
# 2. Apache setup:
#
# sudo a2enmod cgi
# sudo systemctl restart apache2
#
# 3. Place this file at /usr/lib/cgi-bin/asl.rb
#
# 4. Change the THIS_NODE number and FAVORITES list.
#
# 5. Then make the file executable:
#
# sudo chmod 755 /usr/lib/cgi-bin/asl.rb
#
# 6. Allow the www-data user to issue rasterisk commands:
#
# sudo visudo
#
# Add this line and save:
#
# www-data ALL=(asterisk) NOPASSWD: /usr/sbin/rasterisk
#
# Visit the page at http://YOUR_NODE_IP/cgi-bin/asl.rb
#
# WARNING: DO NOT EXPOSE THIS TO THE INTERNET. IT HAS NO SECURITY!
# WARNING: DO NOT EXPOSE THIS TO THE INTERNET. IT HAS NO SECURITY!
# WARNING: DO NOT EXPOSE THIS TO THE INTERNET. IT HAS NO SECURITY!
require 'cgi'
require 'net/http'
require 'json'
require 'uri'
require 'erb'
THIS_NODE = 512345
FAVORITES = {
49562 => 'RCWA',
584801 => 'ECG',
}
cgi = CGI.new
# Handle POST actions
message = nil
if ENV['REQUEST_METHOD'] == 'POST'
node = cgi.params['node']&.first
op = cgi.params['op']&.first
message = `sudo -u asterisk /usr/sbin/rasterisk -x 'rpt cmd #{THIS_NODE} ilink #{op.to_i} #{node.to_i}'`
sleep 1
puts "Status: 302 Found"
puts "Location: asl.rb"
puts
end
# Get connected nodes
nodes = []
begin
nodes_output = `sudo -u asterisk rasterisk -x "rpt stats #{THIS_NODE}"`
connected_nodes = nodes_output.match(/Nodes currently connected to us.*?([\d, ]+)/)
if connected_nodes
nodes = connected_nodes[1].strip.split(', ').map(&:to_i)
end
rescue
nodes = []
end
node_details = nodes.map do |node|
details = JSON.parse(Net::HTTP.get(URI("https://stats.allstarlink.org/api/stats/#{node}")))['node']
{ id: node, callsign: details['callsign'], frequency: details['node_frequency'] }
rescue
{ id: node, callsign: 'N/A', frequency: 'N/A' }
end
template = <<~HTML
Content-Type: text/html
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>asl.rb</title>
<style>
table { border-collapse: collapse; }
td, th { border: 1px solid #ccc; padding: 0.3em 0.5em; }
form { display: inline; }
</style>
</head>
<body>
<h1>ASL - #{THIS_NODE}</h1>
<% if message %>
<p><%= message %></p>
<% end %>
<form method="post">
<input type="hidden" name="op" value="3"/>
<input name="node" placeholder="node number"/>
<input type="submit" value="connect"/>
</form>
<h2>Connected Nodes</h2>
<table>
<tr><th>Node</th><th>Callsign</th><th>Frequency</th><th>Action</th></tr>
<% node_details.each do |node| %>
<tr>
<td><%= node[:id] %></td>
<td><%= node[:callsign] %></td>
<td><%= node[:frequency] %></td>
<td>
<form method="post">
<input type="hidden" name="op" value="1"/>
<input type="hidden" name="node" value="<%= node[:id] %>"/>
<input type="submit" value="disconnect"/>
</form>
</td>
</tr>
<% end %>
</table>
<h2>Favorites</h2>
<% FAVORITES.each do |fav, name| %>
<form method="post">
<input type="hidden" name="op" value="3"/>
<input type="hidden" name="node" value="<%= fav %>"/>
<input type="submit" value="<%= fav %> - <%= name %>"/>
</form>
<% end %>
</body>
</html>
HTML
puts ERB.new(template).result(binding)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment