Skip to content

Commit e18d683

Browse files
authored
Merge pull request #10 from nodetec/relays29
feat: add support for strfry and khatru29
2 parents 13069ad + 611f37e commit e18d683

22 files changed

+744
-111
lines changed

.github/FUNDING.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# These are supported funding model platforms
22

3-
github: christianchiarulli
3+
github: [christianchiarulli, jchiarulli]
44
patreon: chrisatmachine

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
relaywiz
2+
3+
# Ignore .DS_Store files
4+
.DS_Store

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<div align="center"><p>
2-
<h1>Relay Wizard 🪄</h1>
2+
<h1>Relay Wizard 🧙</h1>
33
<a href="https://github.com/nodetec/relaywizard/releases/latest">
44
<img alt="Latest release" src="https://img.shields.io/github/v/release/nodetec/relaywizard?style=for-the-badge&logo=starship&color=C9CBFF&logoColor=D9E0EE&labelColor=302D41" />
55
</a>
@@ -35,7 +35,7 @@ The program will automate the following steps:
3535
To install a relay, spin up a new Debian server, hook up a domain name, and run the following command:
3636

3737
```bash
38-
curl -sL https://relayrunner.org/relaywizard.sh | bash
38+
curl -sL https://relaywizard.com/install.sh | bash
3939
```
4040

4141
## Learn more

cmd/install.go

Lines changed: 82 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package cmd
22

33
import (
4-
"github.com/nodetec/relaywiz/pkg/manager"
5-
"github.com/nodetec/relaywiz/pkg/network"
6-
"github.com/nodetec/relaywiz/pkg/relays/khatru_pyramid"
7-
"github.com/nodetec/relaywiz/pkg/relays/strfry"
8-
"github.com/nodetec/relaywiz/pkg/ui"
4+
"github.com/nodetec/rwz/pkg/manager"
5+
"github.com/nodetec/rwz/pkg/network"
6+
"github.com/nodetec/rwz/pkg/relays/khatru29"
7+
"github.com/nodetec/rwz/pkg/relays/khatru_pyramid"
8+
"github.com/nodetec/rwz/pkg/relays/strfry"
9+
"github.com/nodetec/rwz/pkg/ui"
910
"github.com/pterm/pterm"
1011
"github.com/spf13/cobra"
1112
)
@@ -23,10 +24,10 @@ var installCmd = &cobra.Command{
2324
pterm.Println(pterm.Yellow("Leave email empty if you don't want to receive notifications from Let's Encrypt about your SSL cert."))
2425
pterm.Println()
2526
ssl_email, _ := pterm.DefaultInteractiveTextInput.Show("Email address")
26-
2727
pterm.Println()
28+
2829
// Supported relay options
29-
options := []string{"Khatru Pyramid", "strfry"}
30+
options := []string{"Khatru Pyramid", "strfry", "khatru29"}
3031

3132
// Use PTerm's interactive select feature to present the options to the user and capture their selection
3233
// The Show() method displays the options and waits for the user's input
@@ -35,10 +36,14 @@ var installCmd = &cobra.Command{
3536
// Display the selected option to the user with a green color for emphasis
3637
pterm.Info.Printfln("Selected option: %s", pterm.Green(selectedRelayOption))
3738

39+
var privkey string
3840
var pubkey string
3941
if selectedRelayOption == "Khatru Pyramid" {
4042
pterm.Println()
4143
pubkey, _ = pterm.DefaultInteractiveTextInput.Show("Public key (hex not npub)")
44+
} else if selectedRelayOption == "khatru29" {
45+
pterm.Println()
46+
privkey, _ = pterm.DefaultInteractiveTextInput.Show("Private key (hex not nsec)")
4247
}
4348

4449
pterm.Println()
@@ -48,53 +53,91 @@ var installCmd = &cobra.Command{
4853
// Step 1: Install necessary packages using APT
4954
manager.AptInstallPackages()
5055

51-
if selectedRelayOption == "strfry" {
52-
strfry.AptInstallDependencies()
53-
}
54-
55-
// Step 2: Configure the firewall
56-
network.ConfigureFirewall()
57-
58-
// Step 3: Configure Nginx for HTTP
5956
if selectedRelayOption == "Khatru Pyramid" {
60-
khatru_pyramid.ConfigureNginxHttp(relayDomain)
61-
} else if selectedRelayOption == "strfry" {
62-
strfry.ConfigureNginxHttp(relayDomain)
63-
}
57+
// Step 2: Configure the firewall
58+
network.ConfigureFirewall()
6459

65-
// Step 4: Get SSL certificates
66-
var shouldContinue = network.GetCertificates(relayDomain, ssl_email)
60+
// Step 3: Configure Nginx for HTTP
61+
khatru_pyramid.ConfigureNginxHttp(relayDomain)
6762

68-
if !shouldContinue {
69-
return
70-
}
63+
// Step 4: Get SSL certificates
64+
var shouldContinue = network.GetCertificates(relayDomain, ssl_email)
65+
if !shouldContinue {
66+
return
67+
}
7168

72-
// Step 5: Configure Nginx for HTTPS
73-
if selectedRelayOption == "Khatru Pyramid" {
69+
// Step 5: Configure Nginx for HTTPS
7470
khatru_pyramid.ConfigureNginxHttps(relayDomain)
75-
} else if selectedRelayOption == "strfry" {
76-
strfry.ConfigureNginxHttps(relayDomain)
77-
}
7871

79-
// Step 6: Download and install the relay binary
80-
if selectedRelayOption == "Khatru Pyramid" {
72+
// Step 6: Download and install the relay binary
8173
khatru_pyramid.InstallRelayBinary()
82-
} else if selectedRelayOption == "strfry" {
83-
strfry.InstallRelayBinary()
84-
}
8574

86-
// Step 7: Set up the relay service
87-
if selectedRelayOption == "Khatru Pyramid" {
75+
// Step 7: Set up the relay service
8876
khatru_pyramid.SetupRelayService(relayDomain, pubkey)
77+
78+
// Step 8: Show success messages
79+
khatru_pyramid.SuccessMessages(relayDomain)
8980
} else if selectedRelayOption == "strfry" {
81+
// Step 2: Install necessary strfry package dependencies
82+
strfry.AptInstallDependencies()
83+
84+
// Step 3: Configure the firewall
85+
network.ConfigureFirewall()
86+
87+
// Step 4: Configure Nginx for HTTP
88+
strfry.ConfigureNginxHttp(relayDomain)
89+
90+
// Step 5: Get SSL certificates
91+
var shouldContinue = network.GetCertificates(relayDomain, ssl_email)
92+
if !shouldContinue {
93+
return
94+
}
95+
96+
// Step 6: Configure Nginx for HTTPS
97+
strfry.ConfigureNginxHttps(relayDomain)
98+
99+
// Step 7: Download and install the relay binary
100+
strfry.InstallRelayBinary()
101+
102+
// Step 8: Set up the relay service
90103
strfry.SetupRelayService(relayDomain)
104+
105+
// Step 9: Show success messages
106+
strfry.SuccessMessages(relayDomain)
107+
} else if selectedRelayOption == "khatru29" {
108+
// Step 2: Configure the firewall
109+
network.ConfigureFirewall()
110+
111+
// Step 3: Configure Nginx for HTTP
112+
khatru29.ConfigureNginxHttp(relayDomain)
113+
114+
// Step 4: Get SSL certificates
115+
var shouldContinue = network.GetCertificates(relayDomain, ssl_email)
116+
if !shouldContinue {
117+
return
118+
}
119+
120+
// Step 5: Configure Nginx for HTTPS
121+
khatru29.ConfigureNginxHttps(relayDomain)
122+
123+
// Step 6: Download and install the relay binary
124+
khatru29.InstallRelayBinary()
125+
126+
// Step 7: Set up the relay service
127+
khatru29.SetupRelayService(relayDomain, privkey)
128+
129+
// Step 8: Show success messages
130+
khatru29.SuccessMessages(relayDomain)
91131
}
92132

93133
pterm.Println()
94-
pterm.Println(pterm.Magenta("The installation is complete."))
95-
pterm.Println(pterm.Magenta("You can access your relay at wss://" + relayDomain))
134+
pterm.Println(pterm.Magenta("Join the NODE-TEC Discord to get support:"))
135+
pterm.Println(pterm.Magenta("https://discord.gg/J9gRK5pbWb"))
136+
pterm.Println()
137+
pterm.Println(pterm.Magenta("We plan to use relay groups for support in the future..."))
138+
96139
pterm.Println()
97-
pterm.Println(pterm.Magenta("You can re-run this installer with `relaywiz install`."))
140+
pterm.Println(pterm.Magenta("You can re-run this installer with `rwz install`."))
98141
},
99142
}
100143

cmd/root.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import (
66
)
77

88
var rootCmd = &cobra.Command{
9-
Use: "relaywiz",
9+
Use: "rwz",
1010
Short: "A wizard for relay runners",
11-
Long: `relaywiz is a CLI tool for relays operators that
11+
Long: `rwz is a CLI tool for relays operators that
1212
helps install and configure your relay.`,
1313
}
1414

@@ -30,5 +30,5 @@ func init() {
3030

3131
// Cobra also supports local flags, which will only run
3232
// when this action is called directly.
33-
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
33+
// rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
3434
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module github.com/nodetec/relaywiz
1+
module github.com/nodetec/rwz
22

33
go 1.22.4
44

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package main
22

33
import (
4-
"github.com/nodetec/relaywiz/cmd"
4+
"github.com/nodetec/rwz/cmd"
55
)
66

77
func main() {

pkg/network/certbot.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package network
22

33
import (
44
"fmt"
5-
"github.com/nodetec/relaywiz/pkg/utils"
5+
"github.com/nodetec/rwz/pkg/utils"
66
"github.com/pterm/pterm"
77
"log"
88
"os"

pkg/relays/khatru29/install.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package khatru29
2+
3+
import (
4+
"fmt"
5+
"github.com/pterm/pterm"
6+
"io"
7+
"log"
8+
"net/http"
9+
"os"
10+
"os/exec"
11+
"path/filepath"
12+
)
13+
14+
// Function to download and make the binary executable
15+
func InstallRelayBinary() {
16+
// URL of the binary to download
17+
const downloadURL = "https://github.com/nodetec/relays/releases/download/v0.1.0/khatru29-0.4.0-x86_64-linux-gnu.tar.gz"
18+
19+
// Name of the binary after downloading
20+
const binaryName = "nostr-relay-khatru29"
21+
22+
// Destination directory for the binary
23+
const destDir = "/usr/local/bin"
24+
25+
// Data directory for the relay
26+
const dataDir = "/var/lib/nostr-relay-khatru29"
27+
28+
spinner, _ := pterm.DefaultSpinner.Start("Installing khatru29 relay...")
29+
30+
// Ensure the data directory exists
31+
err := os.MkdirAll(dataDir, 0755)
32+
if err != nil {
33+
log.Fatalf("Error creating data directory: %v", err)
34+
}
35+
36+
// Determine the file name from the URL
37+
tempFileName := filepath.Base(downloadURL)
38+
39+
// Create the temporary file
40+
out, err := os.Create(fmt.Sprintf("/tmp/%s", tempFileName))
41+
if err != nil {
42+
log.Fatalf("Error creating temporary file: %v", err)
43+
}
44+
defer out.Close()
45+
46+
// Download the file
47+
resp, err := http.Get(downloadURL)
48+
if err != nil {
49+
log.Fatalf("Error downloading file: %v", err)
50+
}
51+
defer resp.Body.Close()
52+
53+
// Check server response
54+
if resp.StatusCode != http.StatusOK {
55+
log.Fatalf("Bad status: %s", resp.Status)
56+
}
57+
58+
// Write the body to the temporary file
59+
_, err = io.Copy(out, resp.Body)
60+
if err != nil {
61+
log.Fatalf("Error writing to temporary file: %v", err)
62+
}
63+
64+
// Extract binary
65+
err = exec.Command("tar", "-xf", fmt.Sprintf("/tmp/%s", tempFileName), "-C", fmt.Sprintf("%s", destDir)).Run()
66+
if err != nil {
67+
log.Fatalf("Error extracting binary to /usr/local/bin: %v", err)
68+
}
69+
70+
// TODO
71+
// Currently, the downloaded binary is expected to have a name that matches the binaryName variable
72+
// Ideally, the extracted binary file should be renamed to match the binaryName variable
73+
74+
// Define the final destination path
75+
destPath := filepath.Join(destDir, binaryName)
76+
77+
// Make the file executable
78+
err = os.Chmod(destPath, 0755)
79+
if err != nil {
80+
log.Fatalf("Error making file executable: %v", err)
81+
}
82+
83+
spinner.Success("khatru29 relay installed successfully.")
84+
}

pkg/relays/khatru29/nginx_http.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package khatru29
2+
3+
import (
4+
"fmt"
5+
"github.com/pterm/pterm"
6+
"log"
7+
"os"
8+
"os/exec"
9+
)
10+
11+
// Function to configure nginx for HTTP
12+
func ConfigureNginxHttp(domainName string) {
13+
spinner, _ := pterm.DefaultSpinner.Start("Configuring nginx for HTTP...")
14+
15+
err := os.MkdirAll(fmt.Sprintf("/var/www/%s/.well-known/acme-challenge/", domainName), 0755)
16+
if err != nil {
17+
log.Fatalf("Error creating directories: %v", err)
18+
}
19+
20+
const configFile = "nostr_relay_khatru29.conf"
21+
22+
err = os.Remove(fmt.Sprintf("/etc/nginx/conf.d/%s", configFile))
23+
if err != nil && !os.IsNotExist(err) {
24+
log.Fatalf("Error removing existing nginx configuration: %v", err)
25+
}
26+
27+
var configContent string
28+
29+
configContent = fmt.Sprintf(`map $http_upgrade $connection_upgrade {
30+
default upgrade;
31+
'' close;
32+
}
33+
34+
upstream websocket_khatru29 {
35+
server 0.0.0.0:5577;
36+
}
37+
38+
# %s
39+
server {
40+
listen 80;
41+
listen [::]:80;
42+
server_name %s;
43+
44+
location /.well-known/acme-challenge/ {
45+
root /var/www/%s;
46+
allow all;
47+
}
48+
49+
location / {
50+
proxy_pass http://websocket_khatru29;
51+
proxy_http_version 1.1;
52+
proxy_set_header Upgrade $http_upgrade;
53+
proxy_set_header Connection $connection_upgrade;
54+
proxy_set_header Host $host;
55+
proxy_set_header X-Forwarded-For $remote_addr;
56+
}
57+
}
58+
`, domainName, domainName, domainName)
59+
60+
err = os.WriteFile(fmt.Sprintf("/etc/nginx/conf.d/%s", configFile), []byte(configContent), 0644)
61+
if err != nil {
62+
log.Fatalf("Error writing nginx configuration: %v", err)
63+
}
64+
65+
err = exec.Command("systemctl", "restart", "nginx").Run()
66+
if err != nil {
67+
log.Fatalf("Error reloading nginx: %v", err)
68+
}
69+
70+
spinner.Success("Nginx configured for HTTP")
71+
}

0 commit comments

Comments
 (0)