diff --git a/docker/router-dash/Dockerfile b/docker/routlin-dash/Dockerfile
similarity index 100%
rename from docker/router-dash/Dockerfile
rename to docker/routlin-dash/Dockerfile
diff --git a/docker/router-dash/app/action_add_account.py b/docker/routlin-dash/app/action_add_account.py
similarity index 100%
rename from docker/router-dash/app/action_add_account.py
rename to docker/routlin-dash/app/action_add_account.py
diff --git a/docker/router-dash/app/action_apply_banned_ips.py b/docker/routlin-dash/app/action_apply_banned_ips.py
similarity index 100%
rename from docker/router-dash/app/action_apply_banned_ips.py
rename to docker/routlin-dash/app/action_apply_banned_ips.py
diff --git a/docker/router-dash/app/action_apply_blocklists.py b/docker/routlin-dash/app/action_apply_blocklists.py
similarity index 100%
rename from docker/router-dash/app/action_apply_blocklists.py
rename to docker/routlin-dash/app/action_apply_blocklists.py
diff --git a/docker/router-dash/app/action_apply_ddns_providers.py b/docker/routlin-dash/app/action_apply_ddns_providers.py
similarity index 100%
rename from docker/router-dash/app/action_apply_ddns_providers.py
rename to docker/routlin-dash/app/action_apply_ddns_providers.py
diff --git a/docker/router-dash/app/action_apply_dhcp_reservations.py b/docker/routlin-dash/app/action_apply_dhcp_reservations.py
similarity index 100%
rename from docker/router-dash/app/action_apply_dhcp_reservations.py
rename to docker/routlin-dash/app/action_apply_dhcp_reservations.py
diff --git a/docker/router-dash/app/action_apply_general.py b/docker/routlin-dash/app/action_apply_general.py
similarity index 100%
rename from docker/router-dash/app/action_apply_general.py
rename to docker/routlin-dash/app/action_apply_general.py
diff --git a/docker/router-dash/app/action_apply_host_overrides.py b/docker/routlin-dash/app/action_apply_host_overrides.py
similarity index 100%
rename from docker/router-dash/app/action_apply_host_overrides.py
rename to docker/routlin-dash/app/action_apply_host_overrides.py
diff --git a/docker/router-dash/app/action_apply_iface_config.py b/docker/routlin-dash/app/action_apply_iface_config.py
similarity index 100%
rename from docker/router-dash/app/action_apply_iface_config.py
rename to docker/routlin-dash/app/action_apply_iface_config.py
diff --git a/docker/router-dash/app/action_apply_inter_vlan.py b/docker/routlin-dash/app/action_apply_inter_vlan.py
similarity index 100%
rename from docker/router-dash/app/action_apply_inter_vlan.py
rename to docker/routlin-dash/app/action_apply_inter_vlan.py
diff --git a/docker/router-dash/app/action_apply_interface.py b/docker/routlin-dash/app/action_apply_interface.py
similarity index 100%
rename from docker/router-dash/app/action_apply_interface.py
rename to docker/routlin-dash/app/action_apply_interface.py
diff --git a/docker/router-dash/app/action_apply_mdns.py b/docker/routlin-dash/app/action_apply_mdns.py
similarity index 100%
rename from docker/router-dash/app/action_apply_mdns.py
rename to docker/routlin-dash/app/action_apply_mdns.py
diff --git a/docker/router-dash/app/action_apply_port_forwarding.py b/docker/routlin-dash/app/action_apply_port_forwarding.py
similarity index 100%
rename from docker/router-dash/app/action_apply_port_forwarding.py
rename to docker/routlin-dash/app/action_apply_port_forwarding.py
diff --git a/docker/router-dash/app/action_apply_upstream_dns.py b/docker/routlin-dash/app/action_apply_upstream_dns.py
similarity index 100%
rename from docker/router-dash/app/action_apply_upstream_dns.py
rename to docker/routlin-dash/app/action_apply_upstream_dns.py
diff --git a/docker/router-dash/app/action_apply_vlans.py b/docker/routlin-dash/app/action_apply_vlans.py
similarity index 100%
rename from docker/router-dash/app/action_apply_vlans.py
rename to docker/routlin-dash/app/action_apply_vlans.py
diff --git a/docker/router-dash/app/action_apply_vpn.py b/docker/routlin-dash/app/action_apply_vpn.py
similarity index 98%
rename from docker/router-dash/app/action_apply_vpn.py
rename to docker/routlin-dash/app/action_apply_vpn.py
index 7df9ca2..674e17b 100644
--- a/docker/router-dash/app/action_apply_vpn.py
+++ b/docker/routlin-dash/app/action_apply_vpn.py
@@ -4,7 +4,7 @@ import re
from flask import Blueprint, make_response, redirect, flash, request
from auth import require_level
-from config_utils import load_core, save_core, verify_core_hash, queued_msg, CONFIGS_DIR
+from config_utils import load_core, save_core, verify_core_hash, queued_msg, CONFIGS_DIR, PRODUCT_DISPLAY_NAME
import sanitize
import validation as validate
@@ -103,7 +103,7 @@ def _build_client_conf(vlan, peer_name, peer_ip, private_key, server_pubkey):
allowed_ips = f'{subnet}/{prefix}' if split_tunnel else '0.0.0.0/0'
lines = [
- '# Generated by router-dash',
+ f'# Generated by {PRODUCT_DISPLAY_NAME}',
'',
'[Interface]',
f'PrivateKey = {private_key}',
@@ -125,7 +125,7 @@ def _conf_response(vlan, peer_name, peer_ip, private_key):
iface = _wg_iface(vlan, core)
server_pub = _server_pubkey(iface)
if not server_pub:
- flash('Peer saved. Run sudo python3 ~/router/core.py --apply to generate the server '
+ flash('Peer saved. Run sudo python3 ~/routlin/core.py --apply to generate the server '
'public key, then regenerate this peer to download the client config.', 'warning')
return redirect(_VIEW)
conf = _build_client_conf(vlan, peer_name, peer_ip, private_key, server_pub)
diff --git a/docker/router-dash/app/action_change_password.py b/docker/routlin-dash/app/action_change_password.py
similarity index 100%
rename from docker/router-dash/app/action_change_password.py
rename to docker/routlin-dash/app/action_change_password.py
diff --git a/docker/router-dash/app/action_clear_ddns_log.py b/docker/routlin-dash/app/action_clear_ddns_log.py
similarity index 100%
rename from docker/router-dash/app/action_clear_ddns_log.py
rename to docker/routlin-dash/app/action_clear_ddns_log.py
diff --git a/docker/router-dash/app/action_create_account.py b/docker/routlin-dash/app/action_create_account.py
similarity index 96%
rename from docker/router-dash/app/action_create_account.py
rename to docker/routlin-dash/app/action_create_account.py
index ae5af99..1989eb6 100644
--- a/docker/router-dash/app/action_create_account.py
+++ b/docker/routlin-dash/app/action_create_account.py
@@ -3,6 +3,7 @@ import json, os, bcrypt, secrets, smtplib
from datetime import datetime, timezone, timedelta
from email.message import EmailMessage
from auth import require_level
+from config_utils import PRODUCT_DISPLAY_NAME
import sanitize
bp = Blueprint('action_create_account', __name__)
@@ -31,7 +32,7 @@ def _send_verification_email(to_address, code):
raise RuntimeError('SMTP_HOST is not configured.')
msg = EmailMessage()
- msg['Subject'] = 'Router Dashboard - Email Verification'
+ msg['Subject'] = f'{PRODUCT_DISPLAY_NAME} - Email Verification'
msg['From'] = from_addr
msg['To'] = to_address
msg.set_content(
diff --git a/docker/router-dash/app/action_delete_account.py b/docker/routlin-dash/app/action_delete_account.py
similarity index 100%
rename from docker/router-dash/app/action_delete_account.py
rename to docker/routlin-dash/app/action_delete_account.py
diff --git a/docker/router-dash/app/action_log_in.py b/docker/routlin-dash/app/action_log_in.py
similarity index 100%
rename from docker/router-dash/app/action_log_in.py
rename to docker/routlin-dash/app/action_log_in.py
diff --git a/docker/router-dash/app/action_log_out.py b/docker/routlin-dash/app/action_log_out.py
similarity index 100%
rename from docker/router-dash/app/action_log_out.py
rename to docker/routlin-dash/app/action_log_out.py
diff --git a/docker/router-dash/app/action_save_preferences.py b/docker/routlin-dash/app/action_save_preferences.py
similarity index 100%
rename from docker/router-dash/app/action_save_preferences.py
rename to docker/routlin-dash/app/action_save_preferences.py
diff --git a/docker/router-dash/app/action_verify_email.py b/docker/routlin-dash/app/action_verify_email.py
similarity index 100%
rename from docker/router-dash/app/action_verify_email.py
rename to docker/routlin-dash/app/action_verify_email.py
diff --git a/docker/router-dash/app/api_apply_status.py b/docker/routlin-dash/app/api_apply_status.py
similarity index 100%
rename from docker/router-dash/app/api_apply_status.py
rename to docker/routlin-dash/app/api_apply_status.py
diff --git a/docker/router-dash/app/auth.py b/docker/routlin-dash/app/auth.py
similarity index 100%
rename from docker/router-dash/app/auth.py
rename to docker/routlin-dash/app/auth.py
diff --git a/docker/router-dash/app/config_utils.py b/docker/routlin-dash/app/config_utils.py
similarity index 97%
rename from docker/router-dash/app/config_utils.py
rename to docker/routlin-dash/app/config_utils.py
index a790864..1395126 100644
--- a/docker/router-dash/app/config_utils.py
+++ b/docker/routlin-dash/app/config_utils.py
@@ -8,7 +8,8 @@ DASHBOARD_QUEUE = f'{CONFIGS_DIR}/.dashboard-queue'
DASHBOARD_DONE = f'{CONFIGS_DIR}/.dashboard-done'
DASHBOARD_LAST_RUN = f'{CONFIGS_DIR}/.dashboard-last-run'
DASHBOARD_LOCK = f'{CONFIGS_DIR}/.dashboard-lock'
-DASHB_TIMER_NAME = 'router-dashboard-queue'
+DASHB_TIMER_NAME = 'routlin-dashboard-queue'
+PRODUCT_DISPLAY_NAME = os.environ.get('PRODUCT_DISPLAY_NAME', 'Routlin Dashboard')
DASHB_INTERVAL_SECS = 60
QUEUE_MAX_LINES = 50
diff --git a/docker/router-dash/app/main.py b/docker/routlin-dash/app/main.py
similarity index 100%
rename from docker/router-dash/app/main.py
rename to docker/routlin-dash/app/main.py
diff --git a/docker/router-dash/app/sanitize.py b/docker/routlin-dash/app/sanitize.py
similarity index 100%
rename from docker/router-dash/app/sanitize.py
rename to docker/routlin-dash/app/sanitize.py
diff --git a/docker/router-dash/app/view_page.py b/docker/routlin-dash/app/view_page.py
similarity index 99%
rename from docker/router-dash/app/view_page.py
rename to docker/routlin-dash/app/view_page.py
index c2c17ce..dd134ce 100644
--- a/docker/router-dash/app/view_page.py
+++ b/docker/routlin-dash/app/view_page.py
@@ -4,7 +4,7 @@ import json, re, subprocess, os, sys, html as html_mod
import sanitize
import validation as validate
from datetime import datetime, timezone
-from config_utils import core_hash, get_pending_entries, _seconds_until_next_run, _format_timing, _is_locked, _lock_mtime
+from config_utils import core_hash, get_pending_entries, _seconds_until_next_run, _format_timing, _is_locked, _lock_mtime, PRODUCT_DISPLAY_NAME
bp = Blueprint('view_page', __name__)
@@ -1330,9 +1330,9 @@ def _load_datasource(spec):
def render_layout(view_id, content_html, tokens):
css = _load_css()
level = _client_level()
- titlebar_html = '
Router Dashboard
'
+ titlebar_html = f'{PRODUCT_DISPLAY_NAME}
'
navbar_html = _render_navbar(view_id, level, tokens)
- footer_html = ''
+ footer_html = f''
page_hash = core_hash()
lan_iface = e(tokens.get('GENERAL_LAN_INTERFACE', ''))
@@ -1367,7 +1367,7 @@ def render_layout(view_id, content_html, tokens):
return (f'\n\n\n'
f' \n'
f' \n'
- f' Router Dashboard\n'
+ f' {PRODUCT_DISPLAY_NAME}\n'
f' \n'
f'\n\n'
f'{titlebar_html}\n'
diff --git a/docker/router-dash/data/authorized_accounts.json b/docker/routlin-dash/data/authorized_accounts.json
similarity index 100%
rename from docker/router-dash/data/authorized_accounts.json
rename to docker/routlin-dash/data/authorized_accounts.json
diff --git a/docker/router-dash/data/navbar_content.json b/docker/routlin-dash/data/navbar_content.json
similarity index 100%
rename from docker/router-dash/data/navbar_content.json
rename to docker/routlin-dash/data/navbar_content.json
diff --git a/docker/router-dash/data/page_content.json b/docker/routlin-dash/data/page_content.json
similarity index 99%
rename from docker/router-dash/data/page_content.json
rename to docker/routlin-dash/data/page_content.json
index bc4783b..c5e6ddf 100644
--- a/docker/router-dash/data/page_content.json
+++ b/docker/routlin-dash/data/page_content.json
@@ -13,7 +13,7 @@
"items": [
{
"type": "h1",
- "text": "Router Dashboard"
+ "text": "Routlin Dashboard"
},
{
"type": "p",
diff --git a/docker/router-dash/docker-compose.yml b/docker/routlin-dash/docker-compose.yml
similarity index 76%
rename from docker/router-dash/docker-compose.yml
rename to docker/routlin-dash/docker-compose.yml
index abebb05..722abfb 100644
--- a/docker/router-dash/docker-compose.yml
+++ b/docker/routlin-dash/docker-compose.yml
@@ -1,18 +1,19 @@
-name: router-dash
+name: routlin-dash
services:
flask-app:
- container_name: router-dash
+ container_name: routlin-dash
build: .
ports:
- "25327:25327"
volumes:
- ./data:/data
- - $HOME/router:/configs
- - $HOME/router/validation.py:/app/validation.py
+ - $HOME/routlin:/configs
+ - $HOME/routlin/validation.py:/app/validation.py
- /sys/class/net:/sys/class/net:ro
- /sys/devices:/sys/devices:ro
environment:
+ - PRODUCT_DISPLAY_NAME=Routlin Dashboard
- INITIAL_MANAGER_EMAIL=mgrotke@gmail.com
- SECRET_KEY=ey8hSQCCYE5kQXV8nOg1CB44LSd3AoUet2ZBc3aZlFrwBbazE7aHcxXWyuT97eAObet5jmOL0CjMg0rB1hE4d2SBVYHPfl8De55EiFv307r1QP3Mf5XgOSSCxD3TuD
- SMTP_HOST=smtp.gmail.com
diff --git a/docker/router-dash/requirements.txt b/docker/routlin-dash/requirements.txt
similarity index 100%
rename from docker/router-dash/requirements.txt
rename to docker/routlin-dash/requirements.txt
diff --git a/routlin/DESCRIPTION.txt b/routlin/DESCRIPTION.txt
new file mode 100644
index 0000000..5e697ef
--- /dev/null
+++ b/routlin/DESCRIPTION.txt
@@ -0,0 +1 @@
+Turn any Linux machine with 2 NICs into an enterprise-grade router and firewall. Ditch vendor gated appliances and opaque firmware while keeping your machine fully multipurpose and under your control. Easily manage VLANs, NAT, DNS, DHCP, VPNs, RADIUS, mDNS, and content filtering through a modern interface built on battle-tested Linux tools like dnsmasq, nftables, systemd-networkd, FreeRADIUS, and WireGuard. Designed to integrate seamlessly with existing enterprise and prosumer networking hardware.
diff --git a/router/README.md b/routlin/README.md
similarity index 100%
rename from router/README.md
rename to routlin/README.md
diff --git a/router/core.json b/routlin/core.json
similarity index 100%
rename from router/core.json
rename to routlin/core.json
diff --git a/router/core.py b/routlin/core.py
similarity index 98%
rename from router/core.py
rename to routlin/core.py
index fe88ac1..3489010 100644
--- a/router/core.py
+++ b/routlin/core.py
@@ -16,8 +16,8 @@ VLAN's dnsmasq instance loads the merged file for its specific combination,
giving true per-VLAN DNS filtering. Blocked domains and all their subdomains
return NXDOMAIN via dnsmasq's local=/ syntax.
-nftables rules are applied atomically into dedicated tables (router-nat,
-router-filter) that do not touch Docker-managed tables. A systemd boot
+nftables rules are applied atomically into dedicated tables (routlin-nat,
+routlin-filter) that do not touch Docker-managed tables. A systemd boot
service (core-nat.service) re-applies the rules on every boot.
File layout:
@@ -25,17 +25,17 @@ File layout:
-- raw downloaded blocklist files
merged-.conf -- merged file per unique blocklist combo
- /etc/dnsmasq-router/
+ /etc/dnsmasq-routlin/
.conf -- per-VLAN dnsmasq config
/etc/systemd/system/
- dnsmasq-router-.service -- per-VLAN dnsmasq service unit
- dns-blocklists-update.timer -- daily blocklist refresh timer
- dns-blocklists-update.service -- timer service unit
+ dnsmasq-routlin-.service -- per-VLAN dnsmasq service unit
+ routlin-dns-blocklist-update.timer -- daily blocklist refresh timer
+ routlin-dns-blocklist-update.service -- timer service unit
core-nat.service -- boot service to re-apply nftables rules
/var/lib/misc/
- dnsmasq-router-.leases -- per-VLAN DHCP lease files
+ dnsmasq-routlin-.leases -- per-VLAN DHCP lease files
.dns-metrics -- cumulative lifetime DNS metrics
@@ -107,19 +107,21 @@ from validation import (
resolve_vlan_derived_fields, validate_config,
)
+PRODUCT_NAME = "routlin"
+
SCRIPT_DIR = Path(__file__).parent
CONFIG_FILE = SCRIPT_DIR / "core.json"
BLOCKLIST_DIR = SCRIPT_DIR / "blocklists"
LOG_FILE = SCRIPT_DIR / "core.log"
METRICS_FILE = SCRIPT_DIR / ".dns-metrics"
-DNSMASQ_CONF_DIR = Path("/etc/dnsmasq-router")
+DNSMASQ_CONF_DIR = Path(f"/etc/dnsmasq-{PRODUCT_NAME}")
LEASES_DIR = Path("/var/lib/misc")
NETWORKD_DIR = Path("/etc/systemd/network")
SYSTEMD_DIR = Path("/etc/systemd/system")
-BLIST_TIMER_NAME = "dns-blocklists-update"
+BLIST_TIMER_NAME = f"{PRODUCT_NAME}-dns-blocklist-update"
BLIST_TIMER_FILE = SYSTEMD_DIR / f"{BLIST_TIMER_NAME}.timer"
BLIST_TIMER_SVC_FILE = SYSTEMD_DIR / f"{BLIST_TIMER_NAME}.service"
-DASHB_TIMER_NAME = "router-dashboard-queue"
+DASHB_TIMER_NAME = f"{PRODUCT_NAME}-dashboard-queue"
DASHB_TIMER_FILE = SYSTEMD_DIR / f"{DASHB_TIMER_NAME}.timer"
DASHB_TIMER_SVC_FILE = SYSTEMD_DIR / f"{DASHB_TIMER_NAME}.service"
DASHB_TIMER_INTERVAL_SEC = 60
@@ -253,12 +255,12 @@ def is_physical(vlan):
return vlan["vlan_id"] == 1
def networkd_stem(vlan):
- return f"10-router-{vlan['name']}"
+ return f"10-{PRODUCT_NAME}-{vlan['name']}"
def vlan_service_name(vlan):
if is_wg(vlan):
- return f"dnsmasq-router-{vlan['name']}-{vlan['interface']}"
- return f"dnsmasq-router-{vlan['name']}"
+ return f"dnsmasq-{PRODUCT_NAME}-{vlan['name']}-{vlan['interface']}"
+ return f"dnsmasq-{PRODUCT_NAME}-{vlan['name']}"
def vlan_service_file(vlan):
return SYSTEMD_DIR / f"{vlan_service_name(vlan)}.service"
@@ -267,10 +269,10 @@ def vlan_conf_file(vlan):
return DNSMASQ_CONF_DIR / f"{vlan['name']}.conf"
def vlan_leases_file(vlan):
- return LEASES_DIR / f"dnsmasq-router-{vlan['name']}.leases"
+ return LEASES_DIR / f"dnsmasq-{PRODUCT_NAME}-{vlan['name']}.leases"
def vlan_pid_file(vlan):
- return Path("/run") / f"dnsmasq-router-{vlan['name']}.pid"
+ return Path("/run") / f"dnsmasq-{PRODUCT_NAME}-{vlan['name']}.pid"
# nftables rule list helpers
def rule_enabled(rules):
@@ -352,7 +354,7 @@ def find_legacy_files(managed_interfaces):
to_remove = []
for pattern in ("*.network", "*.netdev"):
for f in NETWORKD_DIR.glob(pattern):
- if f.name.startswith("10-router-"):
+ if f.name.startswith(f"10-{PRODUCT_NAME}-"):
continue
try:
content = f.read_text()
@@ -1153,12 +1155,12 @@ def apply_dnsmasq_instances(data, dry_run=False, start_if_needed=True):
subprocess.run(["systemctl", "daemon-reload"], capture_output=True, text=True)
# Remove stale service units (VLANs removed from config)
- for f in SYSTEMD_DIR.glob("dnsmasq-router-*.service"):
+ for f in SYSTEMD_DIR.glob(f"dnsmasq-{PRODUCT_NAME}-*.service"):
if f.stem not in active_service_stems:
subprocess.run(["systemctl", "disable", "--now", f.stem],
capture_output=True, text=True)
f.unlink()
- n = f.stem.removeprefix("dnsmasq-router-")
+ n = f.stem.removeprefix(f"dnsmasq-{PRODUCT_NAME}-")
stale_conf = DNSMASQ_CONF_DIR / f"{n}.conf"
if stale_conf.exists():
stale_conf.unlink()
@@ -1530,10 +1532,10 @@ def build_nft_config(data, dry_run=False):
line()
# ==========================================================================
- # router-nat table
+ # {PRODUCT_NAME}-nat table
# ==========================================================================
- line("table ip router-nat {")
+ line(f"table ip {PRODUCT_NAME}-nat {{")
line()
line(" chain prerouting {")
line(" type nat hook prerouting priority dstnat - 10; policy accept;")
@@ -1574,10 +1576,10 @@ def build_nft_config(data, dry_run=False):
line()
# ==========================================================================
- # router-filter table
+ # {PRODUCT_NAME}-filter table
# ==========================================================================
- line("table ip router-filter {")
+ line(f"table ip {PRODUCT_NAME}-filter {{")
line()
if banned_v4:
@@ -1732,7 +1734,7 @@ def build_nft_config(data, dry_run=False):
if banned_v6:
line()
- line("table ip6 router-ban {")
+ line(f"table ip6 {PRODUCT_NAME}-ban {{")
line()
line(" set banned_ipv6 {")
line(" type ipv6_addr")
@@ -1767,7 +1769,7 @@ def table_exists(family, name):
return result.returncode == 0
def delete_our_tables():
- for family, table in [("ip", "router-nat"), ("ip", "router-filter"), ("ip6", "router-ban")]:
+ for family, table in [("ip", f"{PRODUCT_NAME}-nat"), ("ip", f"{PRODUCT_NAME}-filter"), ("ip6", f"{PRODUCT_NAME}-ban")]:
if table_exists(family, table):
result = subprocess.run(
["nft", "delete", "table", family, table],
@@ -1872,7 +1874,7 @@ def apply_nftables(data, dry_run=False):
print(f" [{r['protocol'].upper():<4}] {src} -> {dst_str} ({r['description']})")
def show_rules():
- for table in ("router-nat", "router-filter"):
+ for table in (f"{PRODUCT_NAME}-nat", f"{PRODUCT_NAME}-filter"):
result = subprocess.run(
["nft", "list", "table", "ip", table],
capture_output=True, text=True
@@ -1890,7 +1892,7 @@ def install_nat_service():
script_path = Path(__file__).resolve()
service_content = f"""[Unit]
-Description=Apply router NAT and firewall rules
+Description=Apply {PRODUCT_NAME} NAT and firewall rules
After=network-online.target docker.service
Wants=network-online.target docker.service
@@ -2599,7 +2601,7 @@ def disable_all(data):
def _write_client_network(iface, dhcp, static_cidr=None):
"""Remove all router networkd files and write a plain client .network file."""
- for pattern in ("10-router-*.network", "10-router-*.netdev"):
+ for pattern in (f"10-{PRODUCT_NAME}-*.network", f"10-{PRODUCT_NAME}-*.netdev"):
for f in NETWORKD_DIR.glob(pattern):
f.unlink()
print(f"Removed: {f}")
@@ -2793,7 +2795,7 @@ def _dry_run_disable(data, iface, use_dhcp, static_cidr, resolv_ok, dns_choice,
print("[DRY RUN] Based on your selections, --disable would perform the following:")
print()
- print("-- Stopping router services (dry-run) --------------------------------")
+ print(f"-- Stopping {PRODUCT_NAME} services (dry-run) --------------------------------")
print(f" Would disable and stop: {BLIST_TIMER_NAME}.timer")
for vlan in data["vlans"]:
svc = vlan_service_name(vlan)
@@ -2805,7 +2807,7 @@ def _dry_run_disable(data, iface, use_dhcp, static_cidr, resolv_ok, dns_choice,
if svc_f.exists():
print(f" Would remove: {svc_f}")
print(f" Would reload: systemd daemon")
- for table in ("router-nat", "router-filter"):
+ for table in (f"{PRODUCT_NAME}-nat", f"{PRODUCT_NAME}-filter"):
r = subprocess.run(["nft", "list", "table", "ip", table],
capture_output=True, text=True)
if r.returncode == 0:
@@ -2833,8 +2835,8 @@ def _dry_run_disable(data, iface, use_dhcp, static_cidr, resolv_ok, dns_choice,
print()
print("-- Network interface (dry-run) ----------------------------------------")
- router_net = list(NETWORKD_DIR.glob("10-router-*.network"))
- router_dev = list(NETWORKD_DIR.glob("10-router-*.netdev"))
+ router_net = list(NETWORKD_DIR.glob(f"10-{PRODUCT_NAME}-*.network"))
+ router_dev = list(NETWORKD_DIR.glob(f"10-{PRODUCT_NAME}-*.netdev"))
client_file = NETWORKD_DIR / f"10-client-{iface}.network"
for f in router_net + router_dev:
print(f" Would remove: {f}")
@@ -3020,7 +3022,7 @@ def cmd_disable(data, dry_run=False):
_dry_run_disable(data, iface, use_dhcp, static_cidr, resolv_ok, dns_choice, static_nameserver)
return
- print("-- Stopping router services ------------------------------------------")
+ print(f"-- Stopping {PRODUCT_NAME} services ------------------------------------------")
disable_all(data)
print()
diff --git a/router/create_vpn_peer.py b/routlin/create_vpn_peer.py
similarity index 100%
rename from router/create_vpn_peer.py
rename to routlin/create_vpn_peer.py
diff --git a/router/ddns.json b/routlin/ddns.json
similarity index 100%
rename from router/ddns.json
rename to routlin/ddns.json
diff --git a/router/ddns.py b/routlin/ddns.py
similarity index 100%
rename from router/ddns.py
rename to routlin/ddns.py
diff --git a/router/validation.py b/routlin/validation.py
similarity index 99%
rename from router/validation.py
rename to routlin/validation.py
index 23d57b6..c30a700 100644
--- a/router/validation.py
+++ b/routlin/validation.py
@@ -1,8 +1,8 @@
"""
validation.py -- Shared structural validators for core.json fields.
-Lives alongside core.py in ~/router/ and is volume-mounted into the
-router-dash container at /app/validation.py. Importable by both
+Lives alongside core.py in ~/routlin/ and is volume-mounted into the
+routlin-dash container at /app/validation.py. Importable by both
core.py (router host) and the Flask app directly.
Convention: primitive validators accept a raw string and return the