Skip to content

Commit 498da9e

Browse files
authored
Merge pull request #8 from nodetec/pterm-list
feat: implement strfry relay
2 parents ce80449 + ac3201b commit 498da9e

15 files changed

+677
-122
lines changed

cmd/install.go

+44-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package cmd
22

33
import (
4-
"github.com/pterm/pterm"
5-
64
"github.com/nodetec/relaywiz/pkg/manager"
75
"github.com/nodetec/relaywiz/pkg/network"
8-
"github.com/nodetec/relaywiz/pkg/relay"
6+
"github.com/nodetec/relaywiz/pkg/relays/khatru_pyramid"
7+
"github.com/nodetec/relaywiz/pkg/relays/strfry"
98
"github.com/nodetec/relaywiz/pkg/ui"
9+
"github.com/pterm/pterm"
1010
"github.com/spf13/cobra"
1111
)
1212

@@ -23,7 +23,23 @@ var installCmd = &cobra.Command{
2323
pterm.Println(pterm.Yellow("Leave email empty if you don't want to receive notifications from Let's Encrypt about your SSL cert."))
2424
pterm.Println()
2525
ssl_email, _ := pterm.DefaultInteractiveTextInput.Show("Email address")
26-
pubkey, _ := pterm.DefaultInteractiveTextInput.Show("Public key (hex not npub)")
26+
27+
pterm.Println()
28+
// Supported relay options
29+
options := []string{"Khatru Pyramid", "strfry"}
30+
31+
// Use PTerm's interactive select feature to present the options to the user and capture their selection
32+
// The Show() method displays the options and waits for the user's input
33+
selectedRelayOption, _ := pterm.DefaultInteractiveSelect.WithOptions(options).Show()
34+
35+
// Display the selected option to the user with a green color for emphasis
36+
pterm.Info.Printfln("Selected option: %s", pterm.Green(selectedRelayOption))
37+
38+
var pubkey string
39+
if selectedRelayOption == "Khatru Pyramid" {
40+
pterm.Println()
41+
pubkey, _ = pterm.DefaultInteractiveTextInput.Show("Public key (hex not npub)")
42+
}
2743

2844
pterm.Println()
2945
pterm.Println(pterm.Yellow("If you make a mistake, you can always re-run this installer."))
@@ -32,11 +48,19 @@ var installCmd = &cobra.Command{
3248
// Step 1: Install necessary packages using APT
3349
manager.AptInstallPackages()
3450

51+
if selectedRelayOption == "strfry" {
52+
strfry.AptInstallDependencies()
53+
}
54+
3555
// Step 2: Configure the firewall
3656
network.ConfigureFirewall()
3757

3858
// Step 3: Configure Nginx for HTTP
39-
network.ConfigureNginxHttp(relayDomain)
59+
if selectedRelayOption == "Khatru Pyramid" {
60+
khatru_pyramid.ConfigureNginxHttp(relayDomain)
61+
} else if selectedRelayOption == "strfry" {
62+
strfry.ConfigureNginxHttp(relayDomain)
63+
}
4064

4165
// Step 4: Get SSL certificates
4266
var shouldContinue = network.GetCertificates(relayDomain, ssl_email)
@@ -46,13 +70,25 @@ var installCmd = &cobra.Command{
4670
}
4771

4872
// Step 5: Configure Nginx for HTTPS
49-
network.ConfigureNginxHttps(relayDomain)
73+
if selectedRelayOption == "Khatru Pyramid" {
74+
khatru_pyramid.ConfigureNginxHttps(relayDomain)
75+
} else if selectedRelayOption == "strfry" {
76+
strfry.ConfigureNginxHttps(relayDomain)
77+
}
5078

5179
// Step 6: Download and install the relay binary
52-
relay.InstallRelayBinary()
80+
if selectedRelayOption == "Khatru Pyramid" {
81+
khatru_pyramid.InstallRelayBinary()
82+
} else if selectedRelayOption == "strfry" {
83+
strfry.InstallRelayBinary()
84+
}
5385

5486
// Step 7: Set up the relay service
55-
relay.SetupRelayService(relayDomain, pubkey)
87+
if selectedRelayOption == "Khatru Pyramid" {
88+
khatru_pyramid.SetupRelayService(relayDomain, pubkey)
89+
} else if selectedRelayOption == "strfry" {
90+
strfry.SetupRelayService(relayDomain)
91+
}
5692

5793
pterm.Println()
5894
pterm.Println(pterm.Magenta("The installation is complete."))

cmd/root.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
package cmd
22

33
import (
4-
"os"
5-
64
"github.com/spf13/cobra"
5+
"os"
76
)
87

98
var rootCmd = &cobra.Command{

pkg/manager/apt.go

+38-34
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,56 @@
11
package manager
22

33
import (
4-
"os/exec"
5-
4+
"fmt"
65
"github.com/pterm/pterm"
6+
"log"
7+
"os/exec"
78
)
89

9-
// Function to check if a command exists
10-
func commandExists(command string) bool {
11-
_, err := exec.LookPath(command)
12-
return err == nil
10+
// Function to check if a package is installed
11+
func IsPackageInstalled(packageName string) bool {
12+
out, err := exec.Command("dpkg-query", "-W", "-f='${Status}'", packageName).Output()
13+
14+
if err != nil {
15+
if exitError, ok := err.(*exec.ExitError); ok {
16+
errorCode := exitError.ExitCode()
17+
// Package not found
18+
if errorCode == 1 {
19+
return false
20+
} else {
21+
log.Fatalf("Error checking if package is installed: %v", err)
22+
}
23+
}
24+
}
25+
26+
status := string(out)
27+
28+
if status == "'unknown ok not-installed'" {
29+
return false
30+
} else if status == "'install ok installed'" {
31+
return true
32+
}
33+
34+
return false
1335
}
1436

1537
// Function to install necessary packages
1638
func AptInstallPackages() {
1739
spinner, _ := pterm.DefaultSpinner.Start("Updating and installing packages...")
18-
exec.Command("apt", "update", "-qq").Run()
1940

20-
// Check if nginx is installed, install if not
21-
if commandExists("nginx") {
22-
spinner.UpdateText("nginx is already installed.")
23-
} else {
24-
spinner.UpdateText("Installing nginx...")
25-
exec.Command("apt", "install", "-y", "-qq", "nginx").Run()
26-
}
41+
exec.Command("apt", "update", "-qq").Run()
2742

28-
// Check if Certbot is installed, install if not
29-
if commandExists("certbot") {
30-
spinner.UpdateText("Certbot is already installed.")
31-
} else {
32-
spinner.UpdateText("Installing Certbot...")
33-
exec.Command("apt", "install", "-y", "-qq", "certbot", "python3-certbot-nginx").Run()
34-
}
43+
packages := []string{"nginx", "certbot", "python3-certbot-nginx", "ufw", "fail2ban"}
3544

36-
// Check if ufw is installed, install if not
37-
if commandExists("ufw") {
38-
spinner.UpdateText("ufw is already installed.")
39-
} else {
40-
spinner.UpdateText("Installing ufw...")
41-
exec.Command("apt", "install", "-y", "-qq", "ufw").Run()
45+
// Check if package is installed, install if not
46+
for _, p := range packages {
47+
if IsPackageInstalled(p) {
48+
spinner.UpdateText(fmt.Sprintf("%s is already installed.", p))
49+
} else {
50+
spinner.UpdateText(fmt.Sprintf("Installing %s...", p))
51+
exec.Command("apt", "install", "-y", "-qq", p).Run()
52+
}
4253
}
4354

4455
spinner.Success("Packages updated and installed successfully.")
4556
}
46-
47-
// Function to check if a package is installed
48-
func isPackageInstalled(packageName string) bool {
49-
cmd := exec.Command("dpkg", "-l", packageName)
50-
err := cmd.Run()
51-
return err == nil
52-
}

pkg/network/certbot.go

+4-7
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@ package network
33
import (
44
"fmt"
55
"github.com/nodetec/relaywiz/pkg/utils"
6+
"github.com/pterm/pterm"
67
"log"
78
"os"
89
"os/exec"
9-
10-
"github.com/pterm/pterm"
1110
)
1211

1312
// Function to get SSL certificates using Certbot
@@ -33,29 +32,27 @@ func GetCertificates(domainName, email string) bool {
3332

3433
spinner, _ := pterm.DefaultSpinner.Start("Checking SSL certificates...")
3534

36-
dirName := utils.GetDirectoryName(domainName)
37-
3835
// Check if certificates already exist
3936
if utils.FileExists(fmt.Sprintf("/etc/letsencrypt/live/%s/fullchain.pem", domainName)) &&
4037
utils.FileExists(fmt.Sprintf("/etc/letsencrypt/live/%s/privkey.pem", domainName)) {
4138
spinner.Info("SSL certificates already exist.")
4239
return true
4340
}
4441

45-
err := os.MkdirAll(fmt.Sprintf("/var/www/%s/.well-known/acme-challenge/", dirName), 0755)
42+
err := os.MkdirAll(fmt.Sprintf("/var/www/%s/.well-known/acme-challenge/", domainName), 0755)
4643
if err != nil {
4744
log.Fatalf("Error creating directories for Certbot: %v", err)
4845
}
4946

5047
spinner.UpdateText("Obtaining SSL certificates...")
5148
if email == "" {
52-
cmd := exec.Command("certbot", "certonly", "--webroot", "-w", fmt.Sprintf("/var/www/%s", dirName), "-d", domainName, "--agree-tos", "--no-eff-email", "-q", "--register-unsafely-without-email")
49+
cmd := exec.Command("certbot", "certonly", "--webroot", "-w", fmt.Sprintf("/var/www/%s", domainName), "-d", domainName, "--agree-tos", "--no-eff-email", "-q", "--register-unsafely-without-email")
5350
err = cmd.Run()
5451
if err != nil {
5552
log.Fatalf("Certbot failed to obtain the certificate for %s: %v", domainName, err)
5653
}
5754
} else {
58-
cmd := exec.Command("certbot", "certonly", "--webroot", "-w", fmt.Sprintf("/var/www/%s", dirName), "-d", domainName, "--email", email, "--agree-tos", "--no-eff-email", "-q")
55+
cmd := exec.Command("certbot", "certonly", "--webroot", "-w", fmt.Sprintf("/var/www/%s", domainName), "-d", domainName, "--email", email, "--agree-tos", "--no-eff-email", "-q")
5956
err = cmd.Run()
6057
if err != nil {
6158
log.Fatalf("Certbot failed to obtain the certificate for %s: %v", domainName, err)

pkg/network/firewall.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
package network
22

33
import (
4+
"github.com/pterm/pterm"
45
"log"
56
"os/exec"
6-
7-
"github.com/pterm/pterm"
87
)
98

109
// Function to configure the firewall

pkg/relay/install.go pkg/relays/khatru_pyramid/install.go

+14-17
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,29 @@
1-
package relay
1+
package khatru_pyramid
22

33
import (
4+
"github.com/pterm/pterm"
45
"io"
56
"log"
67
"net/http"
78
"os"
89
"path/filepath"
9-
10-
"github.com/pterm/pterm"
1110
)
1211

13-
// URL of the binary to download
14-
const downloadURL = "https://github.com/github-tijlxyz/khatru-pyramid/releases/download/v0.0.5/khatru-pyramid-v0.0.5-linux-amd64"
15-
16-
// Name of the binary after downloading
17-
const binaryName = "nostr-relay-pyramid"
12+
// Function to download and make the binary executable
13+
func InstallRelayBinary() {
14+
// URL of the binary to download
15+
const downloadURL = "https://github.com/github-tijlxyz/khatru-pyramid/releases/download/v0.0.5/khatru-pyramid-v0.0.5-linux-amd64"
1816

19-
// Destination directory for the binary
20-
const destDir = "/usr/local/bin"
17+
// Name of the binary after downloading
18+
const binaryName = "nostr-relay-khatru-pyramid"
2119

22-
// Data directory for the relay
23-
const dataDir = "/var/lib/nostr-relay-pyramid"
20+
// Destination directory for the binary
21+
const destDir = "/usr/local/bin"
2422

25-
// Function to download and make the binary executable
26-
func InstallRelayBinary() {
23+
// Data directory for the relay
24+
const dataDir = "/var/lib/nostr-relay-khatru-pyramid"
2725

28-
spinner, _ := pterm.DefaultSpinner.Start("Installing relay...")
26+
spinner, _ := pterm.DefaultSpinner.Start("Installing Khatru Pyramid relay...")
2927
// Ensure the data directory exists
3028
err := os.MkdirAll(dataDir, 0755)
3129
if err != nil {
@@ -75,6 +73,5 @@ func InstallRelayBinary() {
7573
log.Fatalf("Error making file executable: %v", err)
7674
}
7775

78-
spinner.Success("Relay installed successfully.")
76+
spinner.Success("Khatru Pyramid relay installed successfully.")
7977
}
80-

pkg/network/nginx_http.go pkg/relays/khatru_pyramid/nginx_http.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,33 @@
1-
package network
1+
package khatru_pyramid
22

33
import (
44
"fmt"
5-
"github.com/nodetec/relaywiz/pkg/utils"
5+
// "github.com/nodetec/relaywiz/pkg/utils"
6+
"github.com/pterm/pterm"
67
"log"
78
"os"
89
"os/exec"
9-
10-
"github.com/pterm/pterm"
1110
)
1211

1312
// Function to configure nginx for HTTP
1413
func ConfigureNginxHttp(domainName string) {
15-
1614
spinner, _ := pterm.DefaultSpinner.Start("Configuring nginx for HTTP...")
17-
dirName := utils.GetDirectoryName(domainName)
1815

19-
err := os.MkdirAll(fmt.Sprintf("/var/www/%s/.well-known/acme-challenge/", dirName), 0755)
16+
err := os.MkdirAll(fmt.Sprintf("/var/www/%s/.well-known/acme-challenge/", domainName), 0755)
2017
if err != nil {
2118
log.Fatalf("Error creating directories: %v", err)
2219
}
2320

24-
err = os.Remove("/etc/nginx/conf.d/nostr_relay.conf")
21+
const configFile = "nostr_relay_khatru_pyramid.conf"
22+
23+
err = os.Remove(fmt.Sprintf("/etc/nginx/conf.d/%s", configFile))
2524
if err != nil && !os.IsNotExist(err) {
2625
log.Fatalf("Error removing existing nginx configuration: %v", err)
2726
}
2827

29-
configContent := fmt.Sprintf(`map $http_upgrade $connection_upgrade {
28+
var configContent string
29+
30+
configContent = fmt.Sprintf(`map $http_upgrade $connection_upgrade {
3031
default upgrade;
3132
'' close;
3233
}
@@ -55,9 +56,9 @@ server {
5556
proxy_set_header X-Forwarded-For $remote_addr;
5657
}
5758
}
58-
`, domainName, domainName, dirName)
59+
`, domainName, domainName, domainName)
5960

60-
err = os.WriteFile("/etc/nginx/conf.d/nostr_relay.conf", []byte(configContent), 0644)
61+
err = os.WriteFile(fmt.Sprintf("/etc/nginx/conf.d/%s", configFile), []byte(configContent), 0644)
6162
if err != nil {
6263
log.Fatalf("Error writing nginx configuration: %v", err)
6364
}
@@ -68,5 +69,4 @@ server {
6869
}
6970

7071
spinner.Success("Nginx configured for HTTP")
71-
7272
}

0 commit comments

Comments
 (0)