Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for strfry and khatru29 #10

Merged
merged 5 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading