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: implement strfry relay #8

Merged
merged 1 commit into from
Sep 12, 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
52 changes: 44 additions & 8 deletions cmd/install.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package cmd

import (
"github.com/pterm/pterm"

"github.com/nodetec/relaywiz/pkg/manager"
"github.com/nodetec/relaywiz/pkg/network"
"github.com/nodetec/relaywiz/pkg/relay"
"github.com/nodetec/relaywiz/pkg/relays/khatru_pyramid"
"github.com/nodetec/relaywiz/pkg/relays/strfry"
"github.com/nodetec/relaywiz/pkg/ui"
"github.com/pterm/pterm"
"github.com/spf13/cobra"
)

Expand All @@ -23,7 +23,23 @@ 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")
pubkey, _ := pterm.DefaultInteractiveTextInput.Show("Public key (hex not npub)")

pterm.Println()
// Supported relay options
options := []string{"Khatru Pyramid", "strfry"}

// 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
selectedRelayOption, _ := pterm.DefaultInteractiveSelect.WithOptions(options).Show()

// Display the selected option to the user with a green color for emphasis
pterm.Info.Printfln("Selected option: %s", pterm.Green(selectedRelayOption))

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

pterm.Println()
pterm.Println(pterm.Yellow("If you make a mistake, you can always re-run this installer."))
Expand All @@ -32,11 +48,19 @@ 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
network.ConfigureNginxHttp(relayDomain)
if selectedRelayOption == "Khatru Pyramid" {
khatru_pyramid.ConfigureNginxHttp(relayDomain)
} else if selectedRelayOption == "strfry" {
strfry.ConfigureNginxHttp(relayDomain)
}

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

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

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

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

pterm.Println()
pterm.Println(pterm.Magenta("The installation is complete."))
Expand Down
3 changes: 1 addition & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package cmd

import (
"os"

"github.com/spf13/cobra"
"os"
)

var rootCmd = &cobra.Command{
Expand Down
72 changes: 38 additions & 34 deletions pkg/manager/apt.go
Original file line number Diff line number Diff line change
@@ -1,52 +1,56 @@
package manager

import (
"os/exec"

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

// Function to check if a command exists
func commandExists(command string) bool {
_, err := exec.LookPath(command)
return err == nil
// Function to check if a package is installed
func IsPackageInstalled(packageName string) bool {
out, err := exec.Command("dpkg-query", "-W", "-f='${Status}'", packageName).Output()

if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
errorCode := exitError.ExitCode()
// Package not found
if errorCode == 1 {
return false
} else {
log.Fatalf("Error checking if package is installed: %v", err)
}
}
}

status := string(out)

if status == "'unknown ok not-installed'" {
return false
} else if status == "'install ok installed'" {
return true
}

return false
}

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

// Check if nginx is installed, install if not
if commandExists("nginx") {
spinner.UpdateText("nginx is already installed.")
} else {
spinner.UpdateText("Installing nginx...")
exec.Command("apt", "install", "-y", "-qq", "nginx").Run()
}
exec.Command("apt", "update", "-qq").Run()

// Check if Certbot is installed, install if not
if commandExists("certbot") {
spinner.UpdateText("Certbot is already installed.")
} else {
spinner.UpdateText("Installing Certbot...")
exec.Command("apt", "install", "-y", "-qq", "certbot", "python3-certbot-nginx").Run()
}
packages := []string{"nginx", "certbot", "python3-certbot-nginx", "ufw", "fail2ban"}

// Check if ufw is installed, install if not
if commandExists("ufw") {
spinner.UpdateText("ufw is already installed.")
} else {
spinner.UpdateText("Installing ufw...")
exec.Command("apt", "install", "-y", "-qq", "ufw").Run()
// Check if package is installed, install if not
for _, p := range packages {
if IsPackageInstalled(p) {
spinner.UpdateText(fmt.Sprintf("%s is already installed.", p))
} else {
spinner.UpdateText(fmt.Sprintf("Installing %s...", p))
exec.Command("apt", "install", "-y", "-qq", p).Run()
}
}

spinner.Success("Packages updated and installed successfully.")
}

// Function to check if a package is installed
func isPackageInstalled(packageName string) bool {
cmd := exec.Command("dpkg", "-l", packageName)
err := cmd.Run()
return err == nil
}
11 changes: 4 additions & 7 deletions pkg/network/certbot.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ package network
import (
"fmt"
"github.com/nodetec/relaywiz/pkg/utils"
"github.com/pterm/pterm"
"log"
"os"
"os/exec"

"github.com/pterm/pterm"
)

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

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

dirName := utils.GetDirectoryName(domainName)

// Check if certificates already exist
if utils.FileExists(fmt.Sprintf("/etc/letsencrypt/live/%s/fullchain.pem", domainName)) &&
utils.FileExists(fmt.Sprintf("/etc/letsencrypt/live/%s/privkey.pem", domainName)) {
spinner.Info("SSL certificates already exist.")
return true
}

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

spinner.UpdateText("Obtaining SSL certificates...")
if email == "" {
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")
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")
err = cmd.Run()
if err != nil {
log.Fatalf("Certbot failed to obtain the certificate for %s: %v", domainName, err)
}
} else {
cmd := exec.Command("certbot", "certonly", "--webroot", "-w", fmt.Sprintf("/var/www/%s", dirName), "-d", domainName, "--email", email, "--agree-tos", "--no-eff-email", "-q")
cmd := exec.Command("certbot", "certonly", "--webroot", "-w", fmt.Sprintf("/var/www/%s", domainName), "-d", domainName, "--email", email, "--agree-tos", "--no-eff-email", "-q")
err = cmd.Run()
if err != nil {
log.Fatalf("Certbot failed to obtain the certificate for %s: %v", domainName, err)
Expand Down
3 changes: 1 addition & 2 deletions pkg/network/firewall.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package network

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

"github.com/pterm/pterm"
)

// Function to configure the firewall
Expand Down
31 changes: 14 additions & 17 deletions pkg/relay/install.go → pkg/relays/khatru_pyramid/install.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
package relay
package khatru_pyramid

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

"github.com/pterm/pterm"
)

// URL of the binary to download
const downloadURL = "https://github.com/github-tijlxyz/khatru-pyramid/releases/download/v0.0.5/khatru-pyramid-v0.0.5-linux-amd64"

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

// Destination directory for the binary
const destDir = "/usr/local/bin"
// Name of the binary after downloading
const binaryName = "nostr-relay-khatru-pyramid"

// Data directory for the relay
const dataDir = "/var/lib/nostr-relay-pyramid"
// Destination directory for the binary
const destDir = "/usr/local/bin"

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

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

spinner.Success("Relay installed successfully.")
spinner.Success("Khatru Pyramid relay installed successfully.")
}

Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
package network
package khatru_pyramid

import (
"fmt"
"github.com/nodetec/relaywiz/pkg/utils"
// "github.com/nodetec/relaywiz/pkg/utils"
"github.com/pterm/pterm"
"log"
"os"
"os/exec"

"github.com/pterm/pterm"
)

// Function to configure nginx for HTTP
func ConfigureNginxHttp(domainName string) {

spinner, _ := pterm.DefaultSpinner.Start("Configuring nginx for HTTP...")
dirName := utils.GetDirectoryName(domainName)

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

err = os.Remove("/etc/nginx/conf.d/nostr_relay.conf")
const configFile = "nostr_relay_khatru_pyramid.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)
}

configContent := fmt.Sprintf(`map $http_upgrade $connection_upgrade {
var configContent string

configContent = fmt.Sprintf(`map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
Expand Down Expand Up @@ -55,9 +56,9 @@ server {
proxy_set_header X-Forwarded-For $remote_addr;
}
}
`, domainName, domainName, dirName)
`, domainName, domainName, domainName)

err = os.WriteFile("/etc/nginx/conf.d/nostr_relay.conf", []byte(configContent), 0644)
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)
}
Expand All @@ -68,5 +69,4 @@ server {
}

spinner.Success("Nginx configured for HTTP")

}
Loading
Loading