-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstartup.py
246 lines (192 loc) · 6.79 KB
/
startup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
import logging
import os
import shutil
import sys
logging.basicConfig(
format="%(asctime)s %(levelname)-8s %(message)s",
level=logging.DEBUG,
datefmt="%Y-%m-%d %H:%M:%S",
)
logger = logging.getLogger()
def execute(cmd):
logger.info("Executing " + cmd)
return os.system(cmd)
SAMPLE_NGINX_CONF = """server {{
location / {{
proxy_pass http://127.0.0.1:9001/;
}}
server_name {domain};
listen [::]:80 ipv6only=on;
listen 80;
}}"""
class Component:
def __init__(self, name):
self.name = name
def dep_comps(self):
return []
def dep_pkgs(self):
return []
def install(self):
logger.info("Installing component " + self.name)
# when installation requires user to specify something (e.g. host / port)
def get_input(self, msg):
return input("[INPUT {}] {}:".format(self.name, msg))
def run(self):
pass
class NginxDomain(Component):
domain: str
def __init__(self):
Component.__init__(self, "NginxDomain")
def dep_pkgs(self):
return ["certbot", "python3-certbot-nginx", "nginx"]
def install(self):
Component.install(self)
self.domain = self.get_input("Insert your fqdn")
with open("/etc/nginx/sites-enabled/default", "w") as f:
f.write(SAMPLE_NGINX_CONF.format(domain=self.domain))
def run(self):
execute("systemctl reload nginx")
execute(f"certbot --nginx -d {self.domain}")
def descr(self):
return """Bootstraps nginx + asks you for your domain to obtain the certificate from certbot"""
class Docker(Component):
def __init__(self):
Component.__init__(self, "Docker")
def dep_pkgs(self):
return [
"apt-transport-https",
"ca-certificates",
"curl",
"gnupg-agent",
"software-properties-common",
]
def install(self):
Component.install(self)
execute("curl -sSL https://get.docker.com | sh")
# add noobgam to docker group for convenience
execute("usermod -aG docker noobgam")
def run(self):
pass
def descr(self):
return """Container service
Docker container engine, allows development of portable & scalable apps"""
class AWSCLI(Component):
def __init__(self):
Component.__init__(self, "AWSCLI")
def dep_pkgs(self):
return ["curl", "python3-pip", "unzip"]
def install(self):
Component.install(self)
execute("curl -sSL https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o awscliv2.zip")
execute("unzip awscliv2.zip")
execute("./aws/install")
execute("rm -rf awscliv2.zip aws")
def run(self):
execute("sudo -u noobgam aws configure")
def descr(self):
return "AWS Command Line Interface\nAllows managing AWS services directly from the terminal"
class NodeExporter(Component):
def __init__(self):
Component.__init__(self, "NodeExporter")
def dep_pkgs(self):
return ["wget", "tar", "cron"]
def install(self):
Component.install(self)
execute("wget https://github.com/prometheus/node_exporter/releases/download/v1.8.0/node_exporter-1.8.0.linux-amd64.tar.gz")
execute("tar -xvf node_exporter-1.8.0.linux-amd64.tar.gz")
execute("mv node_exporter-1.8.0.linux-amd64/node_exporter /bin/")
execute("rm -rf node_exporter-1.8.0.linux-amd64.tar.gz node_exporter-1.8.0.linux-amd64")
execute('(crontab -l ; echo "@reboot /bin/node_exporter >/dev/null 2>&1") | crontab -')
def run(self):
execute('/bin/node_exporter >/dev/null 2>&1 &')
def descr(self):
return "Node exporter setup"
class VNC(Component):
"""
Installs tightvnc on host
"""
def __init__(self):
Component.__init__(self, "VNC")
def dep_comps(slef):
return []
def dep_pkgs(self):
# I literally have no idea whatsoever which of these is necessary, but removal of most of them leads to undesired side effects.
return [
"xserver-xorg-core",
"xserver-xorg-input-all",
"tightvncserver",
"xserver-xorg-video-fbdev",
"libx11-6",
"x11-common",
"x11-utils",
"x11-xkb-utils",
"x11-xserver-utils",
"xterm",
"lightdm",
"openbox",
"gnome-panel",
"gnome-settings-daemon",
"metacity",
"nautilus",
"gnome-terminal",
"ubuntu-desktop",
"terminator",
]
def install(self):
global workdir
shutil.copytree(os.path.join(workdir, ".vnc"), "/home/noobgam/.vnc")
execute("chown -R noobgam:nogroup /home/noobgam/.vnc")
execute("chmod +x /home/noobgam/.vnc/xstartup")
def run(self):
execute("tightvncserver -geometry 1920x1080")
def descr(self):
return """TightVNC server
Used to connect to remote desktop, via non-ssh way"""
ALL_COMPONENTS = [Docker(), NginxDomain(), VNC(), AWSCLI(), NodeExporter()]
if __name__ == "__main__":
if os.getuid() != 0:
logger.error("This script must be run as root")
exit(1)
if len(sys.argv) > 1:
global workdir
workdir = sys.argv[1]
install = input("Want to install anything? y(Y)/n(N)")
if install in "nN":
exit(0)
while True:
logger.info(f"Avaliable components: {', '.join([component.name for component in ALL_COMPONENTS])}")
install = input("What would you like to install?\n")
parsed = list(map(lambda x: x.strip(), install.split(",")))
logger.info(parsed)
error = False
for word in parsed:
matches = [x for x in ALL_COMPONENTS if word in x.name]
if len(matches) == 0:
logger.error("Don't know what to do with {}".format(word))
error = True
break
elif len(matches) > 1:
matchNames = list(map(lambda x: x.name, matches))
logger.error(
"Conflicting components found, which of {} do you want to install?".format(
matchNames
)
)
error = True
break
if error:
print("Some error occurred, try again.")
else:
comps = []
for word in parsed:
matches = [x for x in ALL_COMPONENTS if word in x.name]
comps.append(matches[0])
deps = set()
for comp in comps:
deps = deps.union(comp.dep_pkgs())
execute("apt install {} -y".format(" ".join(deps)))
for comp in comps:
comp.install()
for comp in comps:
comp.run()
break