summaryrefslogtreecommitdiffstats
path: root/cmd/deploy/init.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/deploy/init.go')
-rw-r--r--cmd/deploy/init.go154
1 files changed, 154 insertions, 0 deletions
diff --git a/cmd/deploy/init.go b/cmd/deploy/init.go
new file mode 100644
index 0000000..72c7d53
--- /dev/null
+++ b/cmd/deploy/init.go
@@ -0,0 +1,154 @@
1package main
2
3import (
4 "flag"
5 "fmt"
6 "os"
7 "strings"
8
9 "github.com/bdw/deploy/internal/config"
10 "github.com/bdw/deploy/internal/ssh"
11 "github.com/bdw/deploy/internal/state"
12)
13
14func runInit(args []string) {
15 fs := flag.NewFlagSet("init", flag.ExitOnError)
16 host := fs.String("host", "", "VPS host (SSH config alias or user@host)")
17 fs.Parse(args)
18
19 // Get host from flag or config
20 if *host == "" {
21 cfg, err := config.Load()
22 if err != nil {
23 fmt.Fprintf(os.Stderr, "Error loading config: %v\n", err)
24 os.Exit(1)
25 }
26 *host = cfg.Host
27 }
28
29 if *host == "" {
30 fmt.Fprintf(os.Stderr, "Error: --host is required\n")
31 fs.Usage()
32 os.Exit(1)
33 }
34
35 fmt.Printf("Initializing VPS: %s\n", *host)
36
37 // Connect to VPS
38 client, err := ssh.Connect(*host)
39 if err != nil {
40 fmt.Fprintf(os.Stderr, "Error connecting to VPS: %v\n", err)
41 os.Exit(1)
42 }
43 defer client.Close()
44
45 // Detect OS
46 fmt.Println("→ Detecting OS...")
47 osRelease, err := client.Run("cat /etc/os-release")
48 if err != nil {
49 fmt.Fprintf(os.Stderr, "Error detecting OS: %v\n", err)
50 os.Exit(1)
51 }
52
53 if !strings.Contains(osRelease, "Ubuntu") && !strings.Contains(osRelease, "Debian") {
54 fmt.Fprintf(os.Stderr, "Error: Unsupported OS (only Ubuntu and Debian are supported)\n")
55 os.Exit(1)
56 }
57 fmt.Println(" ✓ Detected Ubuntu/Debian")
58
59 // Check if Caddy is already installed
60 fmt.Println("→ Checking for Caddy...")
61 _, err = client.Run("which caddy")
62 if err == nil {
63 fmt.Println(" ✓ Caddy already installed")
64 } else {
65 // Install Caddy
66 fmt.Println(" Installing Caddy...")
67 installCaddy(client)
68 fmt.Println(" ✓ Caddy installed")
69 }
70
71 // Create Caddyfile
72 fmt.Println("→ Configuring Caddy...")
73 caddyfile := `{
74 email admin@example.com
75}
76
77import /etc/caddy/sites-enabled/*
78`
79 if err := client.WriteSudoFile("/etc/caddy/Caddyfile", caddyfile); err != nil {
80 fmt.Fprintf(os.Stderr, "Error creating Caddyfile: %v\n", err)
81 os.Exit(1)
82 }
83 fmt.Println(" ✓ Caddyfile created")
84
85 // Create directories
86 fmt.Println("→ Creating directories...")
87 if _, err := client.RunSudo("mkdir -p /etc/deploy/env"); err != nil {
88 fmt.Fprintf(os.Stderr, "Error creating /etc/deploy/env: %v\n", err)
89 os.Exit(1)
90 }
91 if _, err := client.RunSudo("mkdir -p /etc/caddy/sites-enabled"); err != nil {
92 fmt.Fprintf(os.Stderr, "Error creating /etc/caddy/sites-enabled: %v\n", err)
93 os.Exit(1)
94 }
95 fmt.Println(" ✓ Directories created")
96
97 // Enable and start Caddy
98 fmt.Println("→ Starting Caddy...")
99 if _, err := client.RunSudo("systemctl enable caddy"); err != nil {
100 fmt.Fprintf(os.Stderr, "Error enabling Caddy: %v\n", err)
101 os.Exit(1)
102 }
103 if _, err := client.RunSudo("systemctl restart caddy"); err != nil {
104 fmt.Fprintf(os.Stderr, "Error starting Caddy: %v\n", err)
105 os.Exit(1)
106 }
107 fmt.Println(" ✓ Caddy started")
108
109 // Verify Caddy is running
110 fmt.Println("→ Verifying installation...")
111 output, err := client.RunSudo("systemctl is-active caddy")
112 if err != nil || strings.TrimSpace(output) != "active" {
113 fmt.Fprintf(os.Stderr, "Warning: Caddy may not be running properly\n")
114 } else {
115 fmt.Println(" ✓ Caddy is active")
116 }
117
118 // Initialize local state if needed
119 st, err := state.Load()
120 if err != nil {
121 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
122 os.Exit(1)
123 }
124 st.GetHost(*host) // Ensure host exists in state
125 if err := st.Save(); err != nil {
126 fmt.Fprintf(os.Stderr, "Error saving state: %v\n", err)
127 os.Exit(1)
128 }
129
130 fmt.Println("\n✓ VPS initialized successfully!")
131 fmt.Println("\nNext steps:")
132 fmt.Println(" 1. Deploy a Go app:")
133 fmt.Printf(" deploy deploy --host %s --binary ./myapp --domain api.example.com\n", *host)
134 fmt.Println(" 2. Deploy a static site:")
135 fmt.Printf(" deploy deploy --host %s --static --dir ./dist --domain example.com\n", *host)
136}
137
138func installCaddy(client *ssh.Client) {
139 commands := []string{
140 "apt-get update",
141 "apt-get install -y debian-keyring debian-archive-keyring apt-transport-https curl",
142 "curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg",
143 "curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list",
144 "apt-get update",
145 "apt-get install -y caddy",
146 }
147
148 for _, cmd := range commands {
149 if _, err := client.RunSudo(cmd); err != nil {
150 fmt.Fprintf(os.Stderr, "Error running: %s\nError: %v\n", cmd, err)
151 os.Exit(1)
152 }
153 }
154}