-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtipi-tricks
429 lines (359 loc) · 14.6 KB
/
tipi-tricks
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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
#!/usr/bin/python3
import click
import os
import subprocess
import json
CONFIG_FILE = 'etc/runtipi_config.json'
CONFIG_DIR = os.path.dirname(os.path.abspath(__file__))
CONFIG_PATH = os.path.join(CONFIG_DIR, CONFIG_FILE)
SERVICE_FILE = '/etc/systemd/system/monitor_shares.service'
DRIVE_SPACE_SERVICE_FILE = '/etc/systemd/system/monitor_drive_space.service'
TEMP_SENSOR_SERVICE_FILE = '/etc/systemd/system/monitor_temp_sensor.service'
SCRIPT_NAME = os.path.basename(__file__)
CRONTAB_FILE = '/etc/crontab'
SYSTEM_CRON_ENTRY = f"30 0 * * * root apt update -y && apt upgrade -y && apt autoremove -y && apt clean -y && [ -f /var/run/reboot-required ] && reboot \n"
APP_CRON_ENTRY = f"15 0 * * * root cd {CONFIG_DIR} && ./{SCRIPT_NAME} --update-apps\n"
TIPI_CRON_ENTRY = f"0 0 * * * root cd {CONFIG_DIR} && ./runtipi-cli update latest\n"
BACKUP_CRON_ENTRY = f"30 3 * * * root cd {CONFIG_DIR} && ./runtipi-cli stop && {CONFIG_DIR}/bin/scheduled_tipi_backup.py && ./runtipi-cli start\n"
def find_runtipi_cli():
"""Find the runtipi-cli binary and log its path to the configuration file."""
binary_name = 'runtipi-cli'
# Check if config file exists and read the path from it
if os.path.exists(CONFIG_PATH):
with open(CONFIG_PATH, 'r') as config_file:
config = json.load(config_file)
if 'runtipi_cli_path' in config:
if os.path.exists(config['runtipi_cli_path']) and os.access(config['runtipi_cli_path'], os.X_OK):
return config['runtipi_cli_path']
# Check if binary is in PATH
for path in os.getenv('PATH').split(os.pathsep):
full_path = os.path.join(path, binary_name)
if os.path.exists(full_path) and os.access(full_path, os.X_OK):
log_runtipi_cli_path(full_path)
return full_path
# Check default installation directory
default_path = os.path.join(CONFIG_DIR, binary_name)
if os.path.exists(default_path) and os.access(default_path, os.X_OK):
log_runtipi_cli_path(default_path)
return default_path
# Prompt user for installation directory
install_dir = click.prompt('runtipi-cli not found. Please enter the Tipi install directory', type=str)
full_path = os.path.join(install_dir, binary_name)
if os.path.exists(full_path) and os.access(full_path, os.X_OK):
log_runtipi_cli_path(full_path)
return full_path
else:
raise FileNotFoundError('runtipi-cli not found in the provided directory.')
def log_runtipi_cli_path(path):
"""Log the runtipi-cli path to the configuration file."""
if not os.path.exists(os.path.join(CONFIG_DIR, 'etc')):
os.makedirs(os.path.join(CONFIG_DIR, 'etc'))
with open(CONFIG_PATH, 'w') as config_file:
json.dump({'runtipi_cli_path': path}, config_file)
def add_tipi_update_cronjob():
"""Add a cron job to run Tipi updates daily at 00:15 as root."""
# Check if the entry already exists to avoid duplicates
with open(CRONTAB_FILE, 'r') as f:
for line in f:
if TIPI_CRON_ENTRY.strip() in line.strip():
click.echo("Cron job already exists.")
return
# Append the new entry to /etc/crontab
with open(CRONTAB_FILE, 'a') as f:
f.write(TIPI_CRON_ENTRY)
click.echo("Cron job added successfully.")
def remove_tipi_update_cronjob():
"""Remove the cron job that runs Tipi updates daily at 00:15 as root."""
# Read the current crontab contents
with open(CRONTAB_FILE, 'r') as f:
lines = f.readlines()
# Filter out the line to remove
new_lines = [line for line in lines if line.strip() != TIPI_CRON_ENTRY.strip()]
# Write the new crontab contents back to the file
with open(CRONTAB_FILE, 'w') as f:
f.writelines(new_lines)
click.echo("Cron job removed successfully.")
def add_system_update_cronjob():
"""Add a cron job to run system updates daily."""
# Check if the entry already exists to avoid duplicates
with open(CRONTAB_FILE, 'r') as f:
for line in f:
if SYSTEM_CRON_ENTRY.strip() in line.strip():
click.echo("System update cron job already exists.")
return
# Append the new entry to /etc/crontab
with open(CRONTAB_FILE, 'a') as f:
f.write(SYSTEM_CRON_ENTRY)
click.echo("System update cron job added successfully.")
def add_app_update_cronjob():
"""Add a cron job to run app updates daily."""
# Check if the entry already exists to avoid duplicates
with open(CRONTAB_FILE, 'r') as f:
for line in f:
if APP_CRON_ENTRY.strip() in line.strip():
click.echo("App update cron job already exists.")
return
# Append the new entry to /etc/crontab
with open(CRONTAB_FILE, 'a') as f:
f.write(APP_CRON_ENTRY)
click.echo("APP update cron job added successfully.")
def remove_system_update_cronjob():
"""Remove the cron job that runs system updates daily."""
# Read the current crontab contents
with open(CRONTAB_FILE, 'r') as f:
lines = f.readlines()
# Filter out the line to remove
new_lines = [line for line in lines if line.strip() != SYSTEM_CRON_ENTRY.strip()]
# Write the new crontab contents back to the file
with open(CRONTAB_FILE, 'w') as f:
f.writelines(new_lines)
click.echo("System update cron job removed successfully.")
def remove_app_update_cronjob():
"""Remove the cron job that runs system updates daily."""
# Read the current crontab contents
with open(CRONTAB_FILE, 'r') as f:
lines = f.readlines()
# Filter out the line to remove
new_lines = [line for line in lines if line.strip() != APP_CRON_ENTRY.strip()]
# Write the new crontab contents back to the file
with open(CRONTAB_FILE, 'w') as f:
f.writelines(new_lines)
click.echo("App update cron job removed successfully.")
def add_backup_cronjob():
"""Add a cron job to run Tipi backup daily."""
# Check if the entry already exists to avoid duplicates
with open(CRONTAB_FILE, 'r') as f:
for line in f:
if BACKUP_CRON_ENTRY.strip() in line.strip():
click.echo("Backup cron job already exists.")
return
# Append the new entry to /etc/crontab
with open(CRONTAB_FILE, 'a') as f:
f.write(BACKUP_CRON_ENTRY)
click.echo("Backup cron job added successfully.")
def remove_backup_cronjob():
"""Remove the cron job that runs Tipi backup daily."""
# Read the current crontab contents
with open(CRONTAB_FILE, 'r') as f:
lines = f.readlines()
# Filter out the line to remove
new_lines = [line for line in lines if line.strip() != BACKUP_CRON_ENTRY.strip()]
# Write the new crontab contents back to the file
with open(CRONTAB_FILE, 'w') as f:
f.writelines(new_lines)
click.echo("Backup cron job removed successfully.")
def clear_docker_cache():
"""Clear Docker cache by running 'docker system prune -a'."""
click.echo("Clearing Docker cache...")
# Run docker system prune -a with automatic confirmation
subprocess.run(["docker", "system", "prune", "-a", "-f"], check=True)
click.echo("Docker cache cleared successfully.")
def create_service_file(service_file, exec_start):
"""Create system service file."""
service_content = f"""
[Unit]
Description=Monitor Shares Service
[Service]
ExecStart=/usr/bin/python3 {exec_start}
Restart=always
User=root
[Install]
WantedBy=multi-user.target
"""
with open(service_file, 'w') as f:
f.write(service_content)
click.echo("Service file created successfully.")
def remove_service_file(service_file):
"""Remove system service file."""
if os.path.exists(service_file):
os.remove(service_file)
click.echo("Service file removed successfully.")
else:
click.echo("Service file does not exist.")
def enable_service(service_name):
"""Enable and start the service."""
subprocess.run(["systemctl", "daemon-reload"], check=True)
subprocess.run(["systemctl", "enable", service_name], check=True)
subprocess.run(["systemctl", "start", service_name], check=True)
click.echo("Service enabled and started successfully.")
def disable_service(service_name):
"""Disable and stop the service."""
subprocess.run(["systemctl", "stop", service_name], check=True)
subprocess.run(["systemctl", "disable", service_name], check=True)
subprocess.run(["systemctl", "daemon-reload"], check=True)
click.echo("Service disabled and stopped successfully.")
def update_apps():
"""Update all applications in the ./apps directory."""
apps_dir = './apps'
if os.path.exists(apps_dir) and os.path.isdir(apps_dir):
for app_name in os.listdir(apps_dir):
app_path = os.path.join(apps_dir, app_name)
if os.path.isdir(app_path):
subprocess.run([runtipi_cli_path, 'app', 'update', app_name], check=True)
click.echo(f"Updated {app_name} successfully.")
else:
click.echo("No ./apps directory found.")
def install_temp_sensor():
"""Install temp-sensor monitoring."""
click.echo("Installing temp-sensor monitoring...")
subprocess.run([os.path.join(CONFIG_DIR, 'bin/monitor_sensor.py'), '--install'], check=True)
subprocess.run([os.path.join(CONFIG_DIR, 'bin/monitor_sensor.py'), '--config'], check=True)
click.echo("Temp-sensor monitoring installed and started successfully.")
def uninstall_temp_sensor():
"""Uninstall temp-sensor monitoring."""
click.echo("Uninstalling temp-sensor monitoring...")
subprocess.run([os.path.join(CONFIG_DIR, 'bin/monitor_sensor.py'), '--uninstall'], check=True)
click.echo("Temp-sensor monitoring uninstalled successfully.")
try:
runtipi_cli_path = find_runtipi_cli()
except FileNotFoundError as e:
click.echo(e)
exit(1)
@click.group()
@click.option('--update-apps', is_flag=True, hidden=True, callback=lambda ctx, param, value: update_apps() if value else None, expose_value=False, is_eager=True)
def tipi_tricks():
"""Tipi tricks command group."""
pass
@tipi_tricks.group()
def updates():
"""Updates submenu."""
pass
@updates.group()
def tipi():
"""Tipi update options."""
pass
@tipi.command()
def enable():
"""Enable Tipi updates."""
click.echo("Enabling Tipi Auto Updates.")
# Add cron job for Tipi updates
add_tipi_update_cronjob()
@tipi.command()
def disable():
"""Disable Tipi updates."""
click.echo("Disabling Tipi Auto Updates.")
# Remove cron job for Tipi updates
remove_tipi_update_cronjob()
@updates.group()
def app():
"""Application update options."""
pass
@app.command()
def enable():
"""Enable Application updates."""
click.echo("Enabling App Auto Updates.")
# Add cron job for App updates
add_app_update_cronjob()
@app.command()
def disable():
"""Disable Application updates."""
click.echo("Disabling App Auto Updates.")
# Remove cron job for App updates
remove_app_update_cronjob()
@updates.group()
def system():
"""System update options."""
pass
@system.command()
def enable():
"""Enable System updates."""
click.echo("Enabling System Auto Updates.")
# Add cron job for system updates
add_system_update_cronjob()
@system.command()
def disable():
"""Disable System updates."""
click.echo("Disabling System Auto Updates.")
# Remove cron job for system updates
remove_system_update_cronjob()
@tipi_tricks.command()
def clear_cache():
"""Clear Docker cache."""
clear_docker_cache()
@tipi_tricks.group()
def monitors():
"""Monitors submenu."""
pass
@monitors.group()
def mount_points():
"""Mount points monitor:
This will monitor all mount points from /etc/fstab.
If a mount fails, stop the containers listed in
./etc/monitor_shares.conf. Will start containers
if the mount points come back up. Will try to bring
up the mountpoints with mount -a once a minute.
Optional: gotify-cli installed in the system path, to get notifications."""
pass
@mount_points.command()
def enable():
"""Enable mount points monitoring."""
click.echo("Enabling mount points monitoring...")
create_service_file(SERVICE_FILE, os.path.join(CONFIG_DIR, 'bin/monitor_shares.py'))
enable_service("monitor_shares.service")
@mount_points.command()
def disable():
"""Disable mount points monitoring."""
click.echo("Disabling mount points monitoring...")
disable_service("monitor_shares.service")
remove_service_file(SERVICE_FILE)
@monitors.group()
def drive_space():
"""Drive space monitor:
This will monitor the disk space usage and trigger notifications or actions
if the space goes below a specified threshold. Threshold can be configured in runtipi/etc/monitor_space.conf.
If drive space reaches 99%, Tipi will stop to prevent possible damage to the system. Tipi will automatically
start again once space is freed.
"""
pass
@drive_space.command()
def enable():
"""Enable drive space monitoring."""
click.echo("Enabling drive space monitoring...")
create_service_file(DRIVE_SPACE_SERVICE_FILE, os.path.join(CONFIG_DIR, 'bin/monitor_space.py'))
enable_service("monitor_drive_space.service")
@drive_space.command()
def disable():
"""Disable drive space monitoring."""
click.echo("Disabling drive space monitoring...")
disable_service("monitor_drive_space.service")
remove_service_file(DRIVE_SPACE_SERVICE_FILE)
@monitors.group()
def temp_sensor():
"""Temp sensor monitor:
This will monitor the temperature sensors and trigger notifications or actions
if the temperature goes above a specified threshold. Threshold can be configured in runtipi/etc/monitor_sensor.conf.
"""
pass
@temp_sensor.command()
def install():
"""Install temp sensor monitoring."""
click.echo("Installing temp sensor monitoring...")
install_temp_sensor()
@temp_sensor.command()
def uninstall():
"""Uninstall temp sensor monitoring."""
click.echo("Uninstalling temp sensor monitoring...")
uninstall_temp_sensor()
@tipi_tricks.group()
def backup():
"""Backup submenu."""
pass
@backup.group()
def tipi_backup():
"""Tipi backup options: Enable for dialy Tipi backups. Max number of backups is configurable in runtipi/etc/scheduled_tipi_backup.conf
"""
pass
@tipi_backup.command()
def enable():
"""Enable Tipi backup."""
click.echo("Enabling Tipi Backup.")
# Add cron job for Tipi backup
add_backup_cronjob()
@tipi_backup.command()
def disable():
"""Disable Tipi backup."""
click.echo("Disabling Tipi Backup.")
# Remove cron job for Tipi backup
remove_backup_cronjob()
if __name__ == '__main__':
tipi_tricks()