feature: the name server's domains have wan.local_fqdn and dns.secondary as their name servers, and a site with dns router gets records of the router's public, internal or external address.
Release / release (push) Successful in 35s

This commit is contained in:
slawek committed 2026-11-06 19:06:48 +01:00
1 parent c2c33cfca0
commit 7f85a1a2e5
16 files changed
+497 -304

No files matched your search

+13 -5
View File
@@ -3,7 +3,9 @@
A site has a name, which also names its folder in /var/lib/vpn-router/sites, host names, a port, the interfaces whose
firewall opens it, TLS (none, acme, ca with --ca, or file with --certificate and --key), the file served for a folder,
whether any path without a file is served that file of the site (--spa), and the group whose members change its files.
whether any path without a file is served that file of the site (--spa), the group whose members change its files, and
who serves the records of its host names (--dns user, elsewhere, or router, the router's name server, with the router's
address of --dns-address).
A change is applied by restarting vpn-router-setup without waiting for it. The answer is text for people on standard
output, and a failure is a message on standard error. With --json the answer is JSON on standard output, and a failure
is {"error": ...} there too. The exit status says what failed: 2 the request is invalid, 3 the site does not exist, 4
@@ -17,7 +19,8 @@ the site exists, 1 anything else. -h or --help shows the commands and their opti
options: [--host H ...] [--no-hosts] [--port P] [--listen internal|external|both] [--tls none|acme|ca|file]
[--ca NAME] [--certificate FILE] [--key FILE] [--index FILE] [--spa | --no-spa]
[--enabled | --no-enabled] [--editors GROUP]
[--enabled | --no-enabled] [--editors GROUP] [--dns user|router]
[--dns-address public|internal|external]
"""
import argparse
@@ -73,6 +76,9 @@ def parse(argv):
'path without a file')
sub.add_argument('--enabled', action=argparse.BooleanOptionalAction, help='serve the site')
sub.add_argument('--editors', metavar='GROUP', help="the group whose members change the files; '' for none")
sub.add_argument('--dns', choices=vpnrouter_sites.DNS, help='who serves the records of the host names')
sub.add_argument('--dns-address', choices=vpnrouter_sites.DNS_ADDRESSES,
help="the router's address in the records of dns router")
if command == 'remove':
sub.add_argument('--content', action='store_true', help='remove the site\'s folder too')
return parser.parse_args(argv)
@@ -82,7 +88,8 @@ def values_of(options):
"""The settings the options give."""
values = {key: getattr(options, option) for key, option in (('port', 'port'), ('listen', 'listen'), ('tls', 'tls'),
('ca', 'ca'), ('index_file', 'index'), ('spa', 'spa'),
('enabled', 'enabled'), ('editors', 'editors'))
('enabled', 'enabled'), ('editors', 'editors'),
('dns', 'dns'), ('dns_address', 'dns_address'))
if getattr(options, option) is not None}
if options.no_hosts:
values['hosts'] = []
@@ -120,9 +127,10 @@ def text_of(answer):
sites = answer['sites'] if 'sites' in answer else [answer]
if not sites:
return 'no sites'
head = ('SITE', 'ENABLED', 'HOSTS', 'PORT', 'LISTEN', 'TLS', 'EDITORS')
head = ('SITE', 'ENABLED', 'HOSTS', 'PORT', 'LISTEN', 'TLS', 'EDITORS', 'DNS')
rows = [(site['name'], 'yes' if site['enabled'] else 'no', ', '.join(site['hosts']) or '*', str(site['port']),
site['listen'], site['tls'] + (f' {site["ca"]}' if site['tls'] == 'ca' else ''), site['editors'] or '-')
site['listen'], site['tls'] + (f' {site["ca"]}' if site['tls'] == 'ca' else ''), site['editors'] or '-',
site['dns'] + (f' {site["dns_address"]}' if site['dns'] == 'router' else ''))
for site in sites]
widths = [max(len(row[column]) for row in (head, *rows)) for column in range(len(head))]
return '\n'.join(' '.join(cell.ljust(width) for cell, width in zip(row, widths)).rstrip() for row in (head, *rows))