Skip to content

Commit

Permalink
Merge pull request #10 from nodetec/relays29
Browse files Browse the repository at this point in the history
feat: add support for strfry and khatru29
  • Loading branch information
jchiarulli authored Sep 16, 2024
2 parents 13069ad + 611f37e commit e18d683
Show file tree
Hide file tree
Showing 22 changed files with 744 additions and 111 deletions.
2 changes: 1 addition & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# These are supported funding model platforms

github: christianchiarulli
github: [christianchiarulli, jchiarulli]
patreon: chrisatmachine
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
relaywiz

# Ignore .DS_Store files
.DS_Store
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div align="center"><p>
<h1>Relay Wizard 🪄</h1>
<h1>Relay Wizard 🧙</h1>
<a href="https://github.com/nodetec/relaywizard/releases/latest">
<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" />
</a>
Expand Down Expand Up @@ -35,7 +35,7 @@ The program will automate the following steps:
To install a relay, spin up a new Debian server, hook up a domain name, and run the following command:

```bash
curl -sL https://relayrunner.org/relaywizard.sh | bash
curl -sL https://relaywizard.com/install.sh | bash
```

## Learn more
Expand Down
121 changes: 82 additions & 39 deletions cmd/install.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package cmd

import (
"github.com/nodetec/relaywiz/pkg/manager"
"github.com/nodetec/relaywiz/pkg/network"
"github.com/nodetec/relaywiz/pkg/relays/khatru_pyramid"
"github.com/nodetec/relaywiz/pkg/relays/strfry"
"github.com/nodetec/relaywiz/pkg/ui"
"github.com/nodetec/rwz/pkg/manager"
"github.com/nodetec/rwz/pkg/network"
"github.com/nodetec/rwz/pkg/relays/khatru29"
"github.com/nodetec/rwz/pkg/relays/khatru_pyramid"
"github.com/nodetec/rwz/pkg/relays/strfry"
"github.com/nodetec/rwz/pkg/ui"
"github.com/pterm/pterm"
"github.com/spf13/cobra"
)
Expand All @@ -23,10 +24,10 @@ var installCmd = &cobra.Command{
pterm.Println(pterm.Yellow("Leave email empty if you don't want to receive notifications from Let's Encrypt about your SSL cert."))
pterm.Println()
ssl_email, _ := pterm.DefaultInteractiveTextInput.Show("Email address")

pterm.Println()

// Supported relay options
options := []string{"Khatru Pyramid", "strfry"}
options := []string{"Khatru Pyramid", "strfry", "khatru29"}

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

var privkey string
var pubkey string
if selectedRelayOption == "Khatru Pyramid" {
pterm.Println()
pubkey, _ = pterm.DefaultInteractiveTextInput.Show("Public key (hex not npub)")
} else if selectedRelayOption == "khatru29" {
pterm.Println()
privkey, _ = pterm.DefaultInteractiveTextInput.Show("Private key (hex not nsec)")
}

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

if selectedRelayOption == "strfry" {
strfry.AptInstallDependencies()
}

// Step 2: Configure the firewall
network.ConfigureFirewall()

// Step 3: Configure Nginx for HTTP
if selectedRelayOption == "Khatru Pyramid" {
khatru_pyramid.ConfigureNginxHttp(relayDomain)
} else if selectedRelayOption == "strfry" {
strfry.ConfigureNginxHttp(relayDomain)
}
// Step 2: Configure the firewall
network.ConfigureFirewall()

// Step 4: Get SSL certificates
var shouldContinue = network.GetCertificates(relayDomain, ssl_email)
// Step 3: Configure Nginx for HTTP
khatru_pyramid.ConfigureNginxHttp(relayDomain)

if !shouldContinue {
return
}
// Step 4: Get SSL certificates
var shouldContinue = network.GetCertificates(relayDomain, ssl_email)
if !shouldContinue {
return
}

// Step 5: Configure Nginx for HTTPS
if selectedRelayOption == "Khatru Pyramid" {
// Step 5: Configure Nginx for HTTPS
khatru_pyramid.ConfigureNginxHttps(relayDomain)
} else if selectedRelayOption == "strfry" {
strfry.ConfigureNginxHttps(relayDomain)
}

// Step 6: Download and install the relay binary
if selectedRelayOption == "Khatru Pyramid" {
// Step 6: Download and install the relay binary
khatru_pyramid.InstallRelayBinary()
} else if selectedRelayOption == "strfry" {
strfry.InstallRelayBinary()
}

// Step 7: Set up the relay service
if selectedRelayOption == "Khatru Pyramid" {
// Step 7: Set up the relay service
khatru_pyramid.SetupRelayService(relayDomain, pubkey)

// Step 8: Show success messages
khatru_pyramid.SuccessMessages(relayDomain)
} else if selectedRelayOption == "strfry" {
// Step 2: Install necessary strfry package dependencies
strfry.AptInstallDependencies()

// Step 3: Configure the firewall
network.ConfigureFirewall()

// Step 4: Configure Nginx for HTTP
strfry.ConfigureNginxHttp(relayDomain)

// Step 5: Get SSL certificates
var shouldContinue = network.GetCertificates(relayDomain, ssl_email)
if !shouldContinue {
return
}

// Step 6: Configure Nginx for HTTPS
strfry.ConfigureNginxHttps(relayDomain)

// Step 7: Download and install the relay binary
strfry.InstallRelayBinary()

// Step 8: Set up the relay service
strfry.SetupRelayService(relayDomain)

// Step 9: Show success messages
strfry.SuccessMessages(relayDomain)
} else if selectedRelayOption == "khatru29" {
// Step 2: Configure the firewall
network.ConfigureFirewall()

// Step 3: Configure Nginx for HTTP
khatru29.ConfigureNginxHttp(relayDomain)

// Step 4: Get SSL certificates
var shouldContinue = network.GetCertificates(relayDomain, ssl_email)
if !shouldContinue {
return
}

// Step 5: Configure Nginx for HTTPS
khatru29.ConfigureNginxHttps(relayDomain)

// Step 6: Download and install the relay binary
khatru29.InstallRelayBinary()

// Step 7: Set up the relay service
khatru29.SetupRelayService(relayDomain, privkey)

// Step 8: Show success messages
khatru29.SuccessMessages(relayDomain)
}

pterm.Println()
pterm.Println(pterm.Magenta("The installation is complete."))
pterm.Println(pterm.Magenta("You can access your relay at wss://" + relayDomain))
pterm.Println(pterm.Magenta("Join the NODE-TEC Discord to get support:"))
pterm.Println(pterm.Magenta("https://discord.gg/J9gRK5pbWb"))
pterm.Println()
pterm.Println(pterm.Magenta("We plan to use relay groups for support in the future..."))

pterm.Println()
pterm.Println(pterm.Magenta("You can re-run this installer with `relaywiz install`."))
pterm.Println(pterm.Magenta("You can re-run this installer with `rwz install`."))
},
}

Expand Down
6 changes: 3 additions & 3 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (
)

var rootCmd = &cobra.Command{
Use: "relaywiz",
Use: "rwz",
Short: "A wizard for relay runners",
Long: `relaywiz is a CLI tool for relays operators that
Long: `rwz is a CLI tool for relays operators that
helps install and configure your relay.`,
}

Expand All @@ -30,5 +30,5 @@ func init() {

// Cobra also supports local flags, which will only run
// when this action is called directly.
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
// rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module github.com/nodetec/relaywiz
module github.com/nodetec/rwz

go 1.22.4

Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package main

import (
"github.com/nodetec/relaywiz/cmd"
"github.com/nodetec/rwz/cmd"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion pkg/network/certbot.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package network

import (
"fmt"
"github.com/nodetec/relaywiz/pkg/utils"
"github.com/nodetec/rwz/pkg/utils"
"github.com/pterm/pterm"
"log"
"os"
Expand Down
84 changes: 84 additions & 0 deletions pkg/relays/khatru29/install.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package khatru29

import (
"fmt"
"github.com/pterm/pterm"
"io"
"log"
"net/http"
"os"
"os/exec"
"path/filepath"
)

// Function to download and make the binary executable
func InstallRelayBinary() {
// URL of the binary to download
const downloadURL = "https://github.com/nodetec/relays/releases/download/v0.1.0/khatru29-0.4.0-x86_64-linux-gnu.tar.gz"

// Name of the binary after downloading
const binaryName = "nostr-relay-khatru29"

// Destination directory for the binary
const destDir = "/usr/local/bin"

// Data directory for the relay
const dataDir = "/var/lib/nostr-relay-khatru29"

spinner, _ := pterm.DefaultSpinner.Start("Installing khatru29 relay...")

// Ensure the data directory exists
err := os.MkdirAll(dataDir, 0755)
if err != nil {
log.Fatalf("Error creating data directory: %v", err)
}

// Determine the file name from the URL
tempFileName := filepath.Base(downloadURL)

// Create the temporary file
out, err := os.Create(fmt.Sprintf("/tmp/%s", tempFileName))
if err != nil {
log.Fatalf("Error creating temporary file: %v", err)
}
defer out.Close()

// Download the file
resp, err := http.Get(downloadURL)
if err != nil {
log.Fatalf("Error downloading file: %v", err)
}
defer resp.Body.Close()

// Check server response
if resp.StatusCode != http.StatusOK {
log.Fatalf("Bad status: %s", resp.Status)
}

// Write the body to the temporary file
_, err = io.Copy(out, resp.Body)
if err != nil {
log.Fatalf("Error writing to temporary file: %v", err)
}

// Extract binary
err = exec.Command("tar", "-xf", fmt.Sprintf("/tmp/%s", tempFileName), "-C", fmt.Sprintf("%s", destDir)).Run()
if err != nil {
log.Fatalf("Error extracting binary to /usr/local/bin: %v", err)
}

// TODO
// Currently, the downloaded binary is expected to have a name that matches the binaryName variable
// Ideally, the extracted binary file should be renamed to match the binaryName variable

// Define the final destination path
destPath := filepath.Join(destDir, binaryName)

// Make the file executable
err = os.Chmod(destPath, 0755)
if err != nil {
log.Fatalf("Error making file executable: %v", err)
}

spinner.Success("khatru29 relay installed successfully.")
}
71 changes: 71 additions & 0 deletions pkg/relays/khatru29/nginx_http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package khatru29

import (
"fmt"
"github.com/pterm/pterm"
"log"
"os"
"os/exec"
)

// Function to configure nginx for HTTP
func ConfigureNginxHttp(domainName string) {
spinner, _ := pterm.DefaultSpinner.Start("Configuring nginx for HTTP...")

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

const configFile = "nostr_relay_khatru29.conf"

err = os.Remove(fmt.Sprintf("/etc/nginx/conf.d/%s", configFile))
if err != nil && !os.IsNotExist(err) {
log.Fatalf("Error removing existing nginx configuration: %v", err)
}

var configContent string

configContent = fmt.Sprintf(`map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream websocket_khatru29 {
server 0.0.0.0:5577;
}
# %s
server {
listen 80;
listen [::]:80;
server_name %s;
location /.well-known/acme-challenge/ {
root /var/www/%s;
allow all;
}
location / {
proxy_pass http://websocket_khatru29;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
`, domainName, domainName, domainName)

err = os.WriteFile(fmt.Sprintf("/etc/nginx/conf.d/%s", configFile), []byte(configContent), 0644)
if err != nil {
log.Fatalf("Error writing nginx configuration: %v", err)
}

err = exec.Command("systemctl", "restart", "nginx").Run()
if err != nil {
log.Fatalf("Error reloading nginx: %v", err)
}

spinner.Success("Nginx configured for HTTP")
}
Loading

0 comments on commit e18d683

Please sign in to comment.