Niver > ServNest

This commit is contained in:
Miraty 2023-01-29 21:09:00 +01:00
parent 3b97b3cc2f
commit b2bfbb7bf8
14 changed files with 66 additions and 57 deletions

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
/db/niver.db /db/servnest.db
/locales/*/C/LC_MESSAGES/messages.mo /locales/*/C/LC_MESSAGES/messages.mo

View File

@ -14,7 +14,7 @@ Allowed server names. Used to make the authentication tokens specific to the ser
You can specify multiple domains: You can specify multiple domains:
``` ```
public_domains[] = "niver.example" public_domains[] = "servnest.example"
public_domains[] = "4example4example4example4example4example4example4example.onion" public_domains[] = "4example4example4example4example4example4example4example.onion"
``` ```
@ -22,7 +22,7 @@ public_domains[] = "4example4example4example4example4example4example4example.oni
Path that is prepended to the HTTP root where the service can be reached. Used for redirections and emitting cookies. Path that is prepended to the HTTP root where the service can be reached. Used for redirections and emitting cookies.
If the service answers at `https://niver.example/niver/`, you need to set `prefix = "/niver"`. If the service answers at `https://servnest.example/servnest/`, you need to set `prefix = "/servnest"`.
### `service_name` ### `service_name`
@ -98,7 +98,7 @@ Filesystem path to the `kzonecheck` binary. Used to check sent plaintext zonefil
### `public_soa_email` ### `public_soa_email`
Administrator email address published in every SOA record. Ends with a `.`, `@` is replaced by a `.`, an hypothetical `.` in the first part of the address is escaped using a `\` before, thus `contact.admin@niver.example` becomes `contact\.admin.niver.example.` Administrator email address published in every SOA record. Ends with a `.`, `@` is replaced by a `.`, an hypothetical `.` in the first part of the address is escaped using a `\` before, thus `contact.admin@servnest.example` becomes `contact\.admin.servnest.example.`
## `[ht]` ## `[ht]`
@ -170,6 +170,10 @@ Filesystem path to the certbot binary. It is used through sudo to get a Let's En
Filesystem paths to the corresponding GNU coreutils binary (other implementations are not tested). (Their PHP counterpart can't be used as they need to act as another user through sudo.) Filesystem paths to the corresponding GNU coreutils binary (other implementations are not tested). (Their PHP counterpart can't be used as they need to act as another user through sudo.)
### `acme_path`
Filesystem path to the root directory that is served when a request hits `.well-known/acme-challenge` on port 80. Certbot places ACME authentication files here to get Let's Encrypt certificates through the HTTP-01 challenge.
### `sftpgo_group` ### `sftpgo_group`
Linux group as who runs SFTPGo. (Gets full permissions on users directories.) Linux group as who runs SFTPGo. (Gets full permissions on users directories.)
@ -178,7 +182,6 @@ Linux group as who runs SFTPGo. (Gets full permissions on users directories.)
Linux user as who runs SFTPGo. (Used to delete files that users created.) Linux user as who runs SFTPGo. (Used to delete files that users created.)
### `ipv6_address`, `ipv4_address` ### `ipv6_address`, `ipv4_address`
Public IPv6 and IPv4 addresses that users must set in their AAAA and A records for a site with dedicated domain. Public IPv6 and IPv4 addresses that users must set in their AAAA and A records for a site with dedicated domain.

View File

@ -1,20 +1,16 @@
# Niver # ServNest
Niver is a set of 3 network services: ServNest (formerly Niver) is software providing a web interface allowing users to manage 3 independent services:
* Public suffix registry * Public suffix registry
* Nameserver * Domain name server
* Static HTTP site hosting * Static HTTP site hosting
## Demo
<https://niver.4.niv.re/>
## Status ## Status
I plan to create and maintain a public stable instance of Niver, but I haven't done so yet. Thus Niver is not yet tested with real world and long-term usages, and is **alpha software**. I plan to create and maintain a public stable instance of ServNest, but I haven't done so yet. Thus it is not yet tested with real world and long-term usages, and is **alpha software**.
## Detailed features ## Detailed services features
### Public suffix registry (`reg`) ### Public suffix registry (`reg`)
@ -23,19 +19,23 @@ I plan to create and maintain a public stable instance of Niver, but I haven't d
* Set a DS record to enable DNSSEC * Set a DS record to enable DNSSEC
* Set Glue records * Set Glue records
* Display your records * Display your records
* Transfer domain to another account
### Nameserver (`ns`) ### Name server (`ns`)
* Host a zone on the server * Host a zone on the server
* Zone file edition through `<textarea>` * Zone file edition through `<textarea>`
* Dedicated forms to set/unset `A`, `AAAA`, `NS`, `TXT`, `CAA`, `SRV`, `MX`, `SRV`, `SSHFP`, `TLSA`, `CNAME`, `DNAME` and `LOC` records * Dedicated forms to set/unset `A`, `AAAA`, `NS`, `TXT`, `CAA`, `SRV`, `MX`, `SRV`, `SSHFP`, `TLSA`, `CNAME`, `DNAME` and `LOC` records
* Display your records or the full zone file * Display your records or the full zone file
### HTTP hosting (`ht`) ### Static HTTP site hosting (`ht`)
* Upload your site's files using SFTP Upload site's files to the server using SFTP. The way the site is accessed can then be choosed:
* Host a static site with a domain name and a Let's Encrypt certificate
* Host a static site with an Onion service (through Tor) * Dedicated domain name and Let's Encrypt certificate
* Dedicated onion service (through Tor)
* Subdomain of a shared root domain
* HTTP subpath of a shared domain
## Software used ## Software used
@ -68,13 +68,13 @@ Tor
## Installation ## Installation
There is currently no proper documentation to install Niver, but you can create a system image or look at configuration files and scripts from [niver-mkosi](https://code.antopie.org/niver/niver-mkosi). There is currently no proper documentation to install ServNest, but you can create a system image or look at configuration files and scripts from [servnest-mkosi](https://code.antopie.org/servnest/servnest-mkosi).
## Contribute ## Contribute
- Git repository : <https://code.antopie.org/niver/niver> - Git repository : <https://code.antopie.org/servnest/servnest>
- Issue tracker : <https://code.antopie.org/niver/niver/issues> - Issue tracker : <https://code.antopie.org/servnest/servnest/issues>
- Matrix channel : [#niver:matrix.antopie.org](matrix:r/niver:matrix.antopie.org) - Matrix channel : [#servnest:matrix.antopie.org](matrix:r/servnest:matrix.antopie.org)
## Direct contact details ## Direct contact details
@ -82,7 +82,7 @@ See <https://miraty.antopie.org/>.
## License ## License
Niver is ethical libre software: you can use, redistribute or modify it under the terms of the CNPL-NAv7+ as found in LICENSE.md or at <https://git.pixie.town/thufie/npl-builder>. ServNest is ethical libre software: you can use, redistribute or modify it under the terms of the CNPL-NAv7+ as found in LICENSE.md or at <https://git.pixie.town/thufie/npl-builder>.
## Similar projects ## Similar projects

View File

@ -1,11 +1,11 @@
; Directives here are described in DOCS/configuration.md ; Directives here are described in DOCS/configuration.md
[common] [common]
root_path = "/srv/niver/core" root_path = "/srv/servnest/core"
public_domains[] = "niver.test" public_domains[] = "servnest.test"
prefix = "" prefix = ""
service_name = "Niver" service_name = "ServNest"
service_emoji = "🪐" service_emoji = "🪺"
[dns] [dns]
knotc_path = "/usr/sbin/knotc" knotc_path = "/usr/sbin/knotc"
@ -13,37 +13,37 @@ kdig_path = "/usr/bin/kdig"
[reg] [reg]
enabled = true enabled = true
suffixes[niver.test.] = "approved" suffixes[servnest.test.] = "approved"
suffixes[test.niver.test.] = "all" suffixes[test.servnest.test.] = "all"
suffixes[old.niver.test.] = "none" suffixes[old.sernnest.test.] = "none"
suffixes_path = "/srv/niver/reg" suffixes_path = "/srv/servnest/reg"
ttl = 86400 ttl = 86400
address = "[::1]:42053" address = "[::1]:42053"
[ns] [ns]
enabled = true enabled = true
knot_zones_path = "/srv/niver/ns" knot_zones_path = "/srv/servnest/ns"
servers[] = "ns1.niver.test." servers[] = "ns1.servnest.test."
servers[] = "ns2.niver.test." servers[] = "ns2.servnest.test."
kzonecheck_path = "/usr/bin/kzonecheck" kzonecheck_path = "/usr/bin/kzonecheck"
public_soa_email = "hostmaster.niver.invalid." public_soa_email = "hostmaster.invalid."
[ht] [ht]
enabled = true enabled = true
ht_path = "/srv/niver/ht" ht_path = "/srv/servnest/ht"
subpath_domain = "ht.niver.test" subpath_domain = "ht.servnest.test"
subpath_path = "/srv/niver/subpath" subpath_path = "/srv/servnest/subpath"
subdomain_domain = "ht.niver.test" subdomain_domain = "ht.servnest.test"
subdomain_path = "/srv/niver/subdomain" subdomain_path = "/srv/servnest/subdomain"
nginx_config_path = "/srv/niver/nginx" nginx_config_path = "/srv/servnest/nginx"
nginx_reload_cmd = "/usr/bin/systemctl reload nginx" nginx_reload_cmd = "/usr/bin/systemctl reload nginx"
tor_config_path = "/srv/niver/tor-config" tor_config_path = "/srv/servnest/tor-config"
tor_keys_path = "/srv/niver/tor-keys" tor_keys_path = "/srv/servnest/tor-keys"
tor_user = "tor" tor_user = "tor"
tor_reload_cmd = "/usr/bin/systemctl reload tor" tor_reload_cmd = "/usr/bin/systemctl reload tor"
@ -54,6 +54,8 @@ cat_path = "/usr/bin/cat"
rm_path = "/usr/bin/rm" rm_path = "/usr/bin/rm"
mkdir_path = "/usr/bin/mkdir" mkdir_path = "/usr/bin/mkdir"
acme_path = "/srv/servnest/acme"
sftpgo_group = "sftpgo" sftpgo_group = "sftpgo"
sftpgo_user = "sftpgo" sftpgo_user = "sftpgo"
@ -63,7 +65,7 @@ ipv4_address = "127.0.0.1"
sftp_pub = "/etc/sftpgo/ed25519.pub" sftp_pub = "/etc/sftpgo/ed25519.pub"
sftp_fp = "/etc/sftpgo/ed25519.fp" sftp_fp = "/etc/sftpgo/ed25519.fp"
sftp_asciiart = "/etc/sftpgo/ed25519.asciiart" sftp_asciiart = "/etc/sftpgo/ed25519.asciiart"
sftp_domain = "sftp.niver.test" sftp_domain = "sftp.servnest.test"
public_sftp_port = 2022 public_sftp_port = 2022
; Will be used in configuration files ; Will be used in configuration files

View File

@ -1,5 +1,5 @@
:root, .niver { :root, .common {
--svc-color: var(--foreground-color); --svc-color: var(--foreground-color);
} }

View File

@ -4,7 +4,7 @@ function output($code, $msg = '', $logs = ['']) {
http_response_code($code); http_response_code($code);
$shortCode = $code / 100 % 10; $shortCode = $code / 100 % 10;
if ($shortCode === 5) if ($shortCode === 5)
error_log('Niver internal error: ' . strip_tags($msg) . implode(LF, $logs)); error_log('Internal error: ' . strip_tags($msg) . implode(LF, $logs));
$final_message = match ($shortCode) { $final_message = match ($shortCode) {
2 => ($msg === '') ? '' : '<p><output>' . _('<strong>Success</strong>: ') . '<em>' . $msg . '</em></output></p>' . LF, 2 => ($msg === '') ? '' : '<p><output>' . _('<strong>Success</strong>: ') . '<em>' . $msg . '</em></output></p>' . LF,
4 => '<p><output>' . _('<strong>User error</strong>: ') . '<em>' . $msg . '</em></output></p>' . LF, 4 => '<p><output>' . _('<strong>User error</strong>: ') . '<em>' . $msg . '</em></output></p>' . LF,

View File

@ -23,7 +23,7 @@ function regDeleteDomain($domain) {
if (file_put_contents($path, $content) === false) if (file_put_contents($path, $content) === false)
output(500, 'Failed to write new registry file.'); output(500, 'Failed to write new registry file.');
// Delete from Niver's database // Delete from database
query('delete', 'registry', [ query('delete', 'registry', [
'domain' => $domain, 'domain' => $domain,
'username' => $_SESSION['id'], 'username' => $_SESSION['id'],

View File

@ -32,7 +32,7 @@ rateLimit();
addSite($_SESSION['id'], $_POST['dir'], $_POST['domain'], 'dns'); addSite($_SESSION['id'], $_POST['dir'], $_POST['domain'], 'dns');
exec('2>&1 ' . CONF['ht']['sudo_path'] . ' ' . CONF['ht']['certbot_path'] . ' certonly' . (($_SESSION['type'] === 'approved') ? '' : ' --test-cert') . ' --key-type rsa --rsa-key-size 3072 --webroot --webroot-path /srv/niver/acme --domain ' . $_POST['domain'], $output, $returnCode); exec('2>&1 ' . CONF['ht']['sudo_path'] . ' ' . CONF['ht']['certbot_path'] . ' certonly' . (($_SESSION['type'] === 'approved') ? '' : ' --test-cert') . ' --key-type rsa --rsa-key-size 3072 --webroot --webroot-path ' . CONF['ht']['acme_path'] . ' --domain ' . $_POST['domain'], $output, $returnCode);
if ($returnCode !== 0) if ($returnCode !== 0)
output(500, 'Certbot failed to get a Let\'s Encrypt certificate.', $output); output(500, 'Certbot failed to get a Let\'s Encrypt certificate.', $output);

View File

@ -46,7 +46,7 @@ if (chmod($knotZonePath, 0660) !== true)
knotcConfExec([ knotcConfExec([
"set 'zone[" . $_POST['domain'] . "]'", "set 'zone[" . $_POST['domain'] . "]'",
"set 'zone[" . $_POST['domain'] . "].template' 'niver'", "set 'zone[" . $_POST['domain'] . "].template' 'servnest'",
]); ]);
output(200, _('Zone created.')); output(200, _('Zone created.'));

View File

@ -1,9 +1,13 @@
# List of subdomains not available to register # List of subdomains not available to register
# #
# They may be forbidden because: # They may be forbidden because:
# - they may be privileged for impersonating Niver, spamming or fishing # - they may be privileged for impersonating, spamming or fishing
# - they are reserved for a project asking for it and deserving such a well-known name # - they are reserved for a project asking for it and deserving such a well-known name
servnest
serv
nest
srvnst
niver niver
# Registry-related # Registry-related

View File

@ -8,7 +8,7 @@
<div> <div>
<label for="subdomain"><?= _('Subdomain') ?></label> <label for="subdomain"><?= _('Subdomain') ?></label>
<br> <br>
<input id="subdomain" pattern="<?= SUBDOMAIN_REGEX ?>" required="" placeholder="niver" name="subdomain" type="text"> <input id="subdomain" pattern="<?= SUBDOMAIN_REGEX ?>" required="" placeholder="servnest" name="subdomain" type="text">
</div> </div>
<div> <div>
<label for="suffix"><?= _('Suffix') ?></label> <label for="suffix"><?= _('Suffix') ?></label>

View File

@ -8,7 +8,7 @@
<div> <div>
<label for="subdomain"><?= _('Subdomain') ?></label> <label for="subdomain"><?= _('Subdomain') ?></label>
<br> <br>
<input id="subdomain" pattern="<?= SUBDOMAIN_REGEX ?>" required="" placeholder="niver" name="subdomain" type="text"> <input id="subdomain" pattern="<?= SUBDOMAIN_REGEX ?>" required="" placeholder="servnest" name="subdomain" type="text">
</div> </div>
<div> <div>
<label for="suffix"><?= _('Suffix') ?></label> <label for="suffix"><?= _('Suffix') ?></label>

View File

@ -1,7 +1,7 @@
<?php <?php
define('CONF', parse_ini_file(__DIR__ . '/config.ini', true, INI_SCANNER_TYPED)); define('CONF', parse_ini_file(__DIR__ . '/config.ini', true, INI_SCANNER_TYPED));
define('DB', new PDO('sqlite:' . CONF['common']['root_path'] . '/db/niver.db')); define('DB', new PDO('sqlite:' . CONF['common']['root_path'] . '/db/servnest.db'));
$locale = 'en'; $locale = 'en';
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
@ -70,7 +70,7 @@ if (!TITLES_LINEAGE[array_key_last(TITLES_LINEAGE)]) {
exit('Page not found.'); exit('Page not found.');
} }
const SESSION_COOKIE_NAME = 'niver-session-key'; const SESSION_COOKIE_NAME = 'servnest-session-key';
function startSession() { function startSession() {
session_start([ session_start([
'name' => SESSION_COOKIE_NAME, 'name' => SESSION_COOKIE_NAME,

View File

@ -25,7 +25,7 @@
<?php <?php
foreach (TITLES_LINEAGE as $id => $title) { foreach (TITLES_LINEAGE as $id => $title) {
$lastTitle = (TITLES_LINEAGE[array_key_last(TITLES_LINEAGE)] === $title); $lastTitle = (TITLES_LINEAGE[array_key_last(TITLES_LINEAGE)] === $title);
echo '<ul><li>' . ($lastTitle ? '<h1>' : '') . '<a' . (($id === 0) ? ' class="niver"' : '') . ' href="' . CONF['common']['prefix'] . ($lastTitle ? '/' . PAGE_URL : '/' . implode('/', array_slice(PAGE_LINEAGE, 0, $id)) . (($lastTitle OR $id === 0) ? '' : '/')) . '">' . $title . '</a>' . ($lastTitle ? '</h1>' : '') . LF; echo '<ul><li>' . ($lastTitle ? '<h1>' : '') . '<a' . (($id === 0) ? ' class="common"' : '') . ' href="' . CONF['common']['prefix'] . ($lastTitle ? '/' . PAGE_URL : '/' . implode('/', array_slice(PAGE_LINEAGE, 0, $id)) . (($lastTitle OR $id === 0) ? '' : '/')) . '">' . $title . '</a>' . ($lastTitle ? '</h1>' : '') . LF;
} }
echo str_repeat('</li></ul>', count(TITLES_LINEAGE)); echo str_repeat('</li></ul>', count(TITLES_LINEAGE));
?> ?>
@ -45,7 +45,7 @@
?> ?>
</main> </main>
<footer> <footer>
<small><?= sprintf(_('%sSource code%s available under %s.'), '<a rel="external" href="https://code.antopie.org/niver/niver" class="niver">', '</a>', '<abbr title="Cooperative Nonviolent Public License No Attribution version 7 or more">CNPL-NAv7+</abbr>') ?></small> <small><?= sprintf(_('%sSource code%s available under %s.'), '<a rel="external" href="https://code.antopie.org/servnest/servnest" class="common">', '</a>', '<abbr title="Cooperative Nonviolent Public License No Attribution version 7 or more">CNPL-NAv7+</abbr>') ?></small>
</footer> </footer>
</body> </body>
</html> </html>