Skip to content

Commit 454ccdb

Browse files
committed
Add SSH provider
1 parent 8d7e7bb commit 454ccdb

File tree

5 files changed

+200
-0
lines changed

5 files changed

+200
-0
lines changed

cmd/flag.go

+20
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,23 @@ var (
117117
Usage: "An optional Google Cloud Zone (default: random)",
118118
}
119119
)
120+
121+
// SSH flags
122+
var (
123+
SshFlag = cli.BoolFlag{
124+
Name: provider.NameSsh,
125+
Usage: "The darknode will be installed on an existing server with SSH",
126+
}
127+
SshUserFlag = cli.StringFlag{
128+
Name: "ssh-user",
129+
Usage: "SSH User",
130+
}
131+
SshHostnameFlag = cli.StringFlag{
132+
Name: "ssh-hostname",
133+
Usage: "SSH Hostname",
134+
}
135+
SshPrivateKeyFlag = cli.StringFlag{
136+
Name: "ssh-private-key",
137+
Usage: "SSH Private key",
138+
}
139+
)

cmd/main.go

+2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ func main() {
4747
DoFlag, DoRegionFlag, DoSizeFlag, DoTokenFlag,
4848
// Google Cloud Platform
4949
GcpFlag, GcpZoneFlag, GcpCredFlag, GcpMachineFlag,
50+
// SSH
51+
SshFlag, SshUserFlag, SshHostnameFlag, SshPrivateKeyFlag,
5052
},
5153
Action: func(c *cli.Context) error {
5254
p, err := provider.ParseProvider(c)

cmd/provider/provider.go

+5
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ var (
3030
NameAws = "aws"
3131
NameDo = "do"
3232
NameGcp = "gcp"
33+
NameSsh = "ssh"
3334
)
3435

3536
var darknodeService = `[Unit]
@@ -68,6 +69,10 @@ func ParseProvider(ctx *cli.Context) (Provider, error) {
6869
return NewGcp(ctx)
6970
}
7071

72+
if ctx.Bool(NameSsh) {
73+
return NewSsh(ctx)
74+
}
75+
7176
return nil, ErrUnknownProvider
7277
}
7378

cmd/provider/ssh.go

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package provider
2+
3+
import (
4+
"github.com/renproject/darknode-cli/darknode"
5+
"github.com/renproject/darknode-cli/util"
6+
"github.com/urfave/cli"
7+
)
8+
9+
type providerSsh struct {
10+
user string
11+
hostname string
12+
priKeyPath string
13+
}
14+
15+
func NewSsh(ctx *cli.Context) (Provider, error) {
16+
user := ctx.String("ssh-user")
17+
hostname := ctx.String("ssh-hostname")
18+
priKeyPath := ctx.String("ssh-private-key")
19+
20+
return providerSsh{
21+
user: user,
22+
hostname: hostname,
23+
priKeyPath: priKeyPath,
24+
}, nil
25+
}
26+
27+
func (p providerSsh) Name() string {
28+
return NameSsh
29+
}
30+
31+
func (p providerSsh) Deploy(ctx *cli.Context) error {
32+
name := ctx.String("name")
33+
tags := ctx.String("tags")
34+
35+
latestVersion, err := util.LatestStableRelease()
36+
if err != nil {
37+
return err
38+
}
39+
40+
// Initialization
41+
network, err := darknode.NewNetwork(ctx.String("network"))
42+
if err != nil {
43+
return err
44+
}
45+
if err := initNode(name, tags, network); err != nil {
46+
return err
47+
}
48+
49+
// Generate terraform config and start deploying
50+
if err := p.tfConfig(name, latestVersion); err != nil {
51+
return err
52+
}
53+
if err := runTerraform(name); err != nil {
54+
return err
55+
}
56+
return outputURL(name)
57+
}

cmd/provider/ssh_template.go

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package provider
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
"text/template"
8+
9+
"github.com/renproject/darknode-cli/util"
10+
)
11+
12+
type sshTerraform struct {
13+
Name string
14+
User string
15+
Hostname string
16+
PriKeyPath string
17+
ConfigPath string
18+
ServiceFile string
19+
LatestVersion string
20+
}
21+
22+
func (p providerSsh) tfConfig(name, latestVersion string) error {
23+
tf := sshTerraform{
24+
Name: name,
25+
User: p.user,
26+
Hostname: p.hostname,
27+
ConfigPath: fmt.Sprintf("~/.darknode/darknodes/%v/config.json", name),
28+
PriKeyPath: fmt.Sprintf(p.priKeyPath),
29+
ServiceFile: darknodeService,
30+
LatestVersion: latestVersion,
31+
}
32+
33+
t, err := template.New("ssh").Parse(sshTemplate)
34+
if err != nil {
35+
return err
36+
}
37+
tfFile, err := os.Create(filepath.Join(util.NodePath(name), "main.tf"))
38+
if err != nil {
39+
return err
40+
}
41+
return t.Execute(tfFile, tf)
42+
}
43+
44+
var sshTemplate = `
45+
resource "null_resource" "darknode" {
46+
provisioner "remote-exec" {
47+
inline = [
48+
"set -x",
49+
"until sudo apt update; do sleep 4; done",
50+
"sudo adduser darknode --gecos \",,,\" --disabled-password",
51+
"sudo rsync --archive --chown=darknode:darknode ~/.ssh /home/darknode",
52+
"until sudo apt-get -y update; do sleep 4; done",
53+
"until sudo apt-get -y upgrade; do sleep 4; done",
54+
"until sudo apt-get -y autoremove; do sleep 4; done",
55+
"until sudo apt-get install ufw; do sleep 4; done",
56+
"sudo ufw limit 22/tcp",
57+
"sudo ufw allow 18514/tcp",
58+
"sudo ufw allow 18515/tcp",
59+
"sudo ufw --force enable",
60+
"until sudo apt-get -y install jq; do sleep 4; done",
61+
]
62+
63+
connection {
64+
host = "{{.Hostname}}"
65+
type = "ssh"
66+
user = "{{.User}}"
67+
private_key = file("{{.PriKeyPath}}")
68+
}
69+
}
70+
71+
provisioner "file" {
72+
source = "{{.ConfigPath}}"
73+
destination = "$HOME/config.json"
74+
75+
connection {
76+
host = "{{.Hostname}}"
77+
type = "ssh"
78+
user = "darknode"
79+
private_key = file("{{.PriKeyPath}}")
80+
}
81+
}
82+
83+
provisioner "remote-exec" {
84+
inline = [
85+
"set -x",
86+
"mkdir -p $HOME/.darknode/bin",
87+
"mkdir -p $HOME/.config/systemd/user",
88+
"mv $HOME/config.json $HOME/.darknode/config.json",
89+
"curl -sL https://www.github.com/renproject/darknode-release/releases/latest/download/darknode > ~/.darknode/bin/darknode",
90+
"chmod +x ~/.darknode/bin/darknode",
91+
"echo {{.LatestVersion}} > ~/.darknode/version",
92+
<<EOT
93+
echo "{{.ServiceFile}}" > ~/.config/systemd/user/darknode.service
94+
EOT
95+
,
96+
"loginctl enable-linger darknode",
97+
"systemctl --user enable darknode.service",
98+
"systemctl --user start darknode.service",
99+
]
100+
101+
connection {
102+
host = "{{.Hostname}}"
103+
type = "ssh"
104+
user = "darknode"
105+
private_key = file("{{.PriKeyPath}}")
106+
}
107+
}
108+
}
109+
110+
output "provider" {
111+
value = "ssh"
112+
}
113+
114+
output "ip" {
115+
value = "{{.Hostname}}"
116+
}`

0 commit comments

Comments
 (0)