Compare commits
	
		
			52 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | fd80ccd2c5 | ||
|  | 9dc0b24399 | ||
|  | 747954e6fb | ||
|  | 274f4f227e | ||
|  | 92197d8d49 | ||
|  | aee06920eb | ||
|  | 5111b17d3c | ||
|  | 2849d8f45d | ||
|  | bac60d9bd4 | ||
|  | 9c797162f4 | ||
|  | 09d184e2f8 | ||
|  | 7bca618906 | ||
|  | 67607103e9 | ||
|  | 73c9956fe4 | ||
|  | b42f2ffe33 | ||
|  | 30a3f185ef | ||
|  | 4f1b41227f | ||
|  | 83b9d13ec9 | ||
|  | cee7896c37 | ||
|  | 0377009d2b | ||
|  | b472f3644e | ||
|  | 5d8ea837c8 | ||
|  | 82de6bc849 | ||
|  | cb4bc68c48 | ||
|  | 3ce6b38247 | ||
|  | 716c0fe979 | ||
|  | c993790b7a | ||
|  | aa32286531 | ||
|  | 6f94abde00 | ||
|  | fa19538c9d | ||
|  | 84c858b878 | ||
|  | 865de142d4 | ||
|  | 9118162553 | ||
|  | f4fc6ee9b4 | ||
|  | 108c38d57b | ||
|  | a1d73eb830 | ||
|  | 997906a610 | ||
|  | b6e5d120d3 | ||
|  | d469d0b435 | ||
|  | e9f823e000 | ||
|  | d7fb76ba74 | ||
|  | b7dde1a0d9 | ||
|  | 15095d8c23 | ||
|  | dfbebc7606 | ||
|  | 895309d93d | ||
|  | bcf50e821a | ||
|  | 30195800dd | ||
|  | 6532b0f149 | ||
|  | 5e108e4057 | ||
|  | c2b2f4d222 | ||
|  | bc4329ad21 | ||
|  | aec6d1b2f6 | 
							
								
								
									
										2
									
								
								.github/workflows/ci-tests.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/ci-tests.yml
									
									
									
									
										vendored
									
									
								
							| @@ -21,7 +21,7 @@ jobs: | ||||
|  | ||||
|       - uses: harmon758/postgresql-action@v1 | ||||
|         with: | ||||
|           postgresql version: "14" | ||||
|           postgresql version: "15" | ||||
|           postgresql db: "pipeline" | ||||
|           postgresql user: "pipeline" | ||||
|           postgresql password: "pipeline123456" | ||||
|   | ||||
| @@ -1,2 +0,0 @@ | ||||
| deb https://nginx.org/packages/debian/ bullseye nginx | ||||
| deb-src https://nginx.org/packages/debian/ bullseye nginx | ||||
| @@ -41,11 +41,15 @@ | ||||
|   with_items: | ||||
|     - "{{ base_pkgs }}" | ||||
|  | ||||
| - name: set arch fact | ||||
|   ansible.builtin.set_fact: | ||||
|     goarch: "{{ 'amd64' if ansible_architecture == 'x86_64' else 'arm64' }}" | ||||
|  | ||||
| - name: download and install golang | ||||
|   tags: golang | ||||
|   become: yes | ||||
|   ansible.builtin.unarchive: | ||||
|     src: "https://go.dev/dl/go{{ go_ver }}.linux-amd64.tar.gz" | ||||
|     src: "https://go.dev/dl/go{{ go_ver }}.linux-{{ goarch }}.tar.gz" | ||||
|     dest: /usr/local | ||||
|     remote_src: yes | ||||
|  | ||||
| @@ -111,7 +115,7 @@ | ||||
|   tags: postgres | ||||
|   become: yes | ||||
|   ansible.builtin.copy: | ||||
|     content: "deb http://apt.postgresql.org/pub/repos/apt bullseye-pgdg main" | ||||
|     content: "deb http://apt.postgresql.org/pub/repos/apt {{ ansible_distribution_release }}-pgdg main" | ||||
|     dest: /etc/apt/sources.list.d/pgdg.list | ||||
|     owner: root | ||||
|     group: root | ||||
| @@ -128,7 +132,7 @@ | ||||
|   tags: postgres | ||||
|   become: yes | ||||
|   ansible.builtin.apt: | ||||
|     pkg: postgresql-14 | ||||
|     pkg: postgresql-15 | ||||
|     state: present | ||||
|     update_cache: yes | ||||
|  | ||||
| @@ -140,7 +144,7 @@ | ||||
|     enabled: yes | ||||
|     state: started | ||||
|  | ||||
| - name: setup database | ||||
| - name: setup trmm database | ||||
|   tags: postgres | ||||
|   become: yes | ||||
|   become_user: postgres | ||||
| @@ -153,6 +157,23 @@ | ||||
|       psql -c "ALTER ROLE {{ db_user }} SET timezone TO 'UTC'" | ||||
|       psql -c "ALTER ROLE {{ db_user }} CREATEDB" | ||||
|       psql -c "GRANT ALL PRIVILEGES ON DATABASE tacticalrmm TO {{ db_user }}" | ||||
|       psql -c "ALTER DATABASE tacticalrmm OWNER TO {{ db_user }}" | ||||
|       psql -c "GRANT USAGE, CREATE ON SCHEMA PUBLIC TO {{ db_user }}" | ||||
|  | ||||
| - name: setup mesh database | ||||
|   tags: postgres | ||||
|   become: yes | ||||
|   become_user: postgres | ||||
|   ansible.builtin.shell: | ||||
|     cmd: | | ||||
|       psql -c "CREATE DATABASE meshcentral" | ||||
|       psql -c "CREATE USER {{ mesh_db_user }} WITH PASSWORD '{{ mesh_db_passwd }}'" | ||||
|       psql -c "ALTER ROLE {{ mesh_db_user }} SET client_encoding TO 'utf8'" | ||||
|       psql -c "ALTER ROLE {{ mesh_db_user }} SET default_transaction_isolation TO 'read committed'" | ||||
|       psql -c "ALTER ROLE {{ mesh_db_user }} SET timezone TO 'UTC'" | ||||
|       psql -c "GRANT ALL PRIVILEGES ON DATABASE meshcentral TO {{ mesh_db_user }}" | ||||
|       psql -c "ALTER DATABASE meshcentral OWNER TO {{ mesh_db_user }}" | ||||
|       psql -c "GRANT USAGE, CREATE ON SCHEMA PUBLIC TO {{ mesh_db_user }}" | ||||
|  | ||||
| - name: create repo dirs | ||||
|   become: yes | ||||
| @@ -202,7 +223,7 @@ | ||||
| - name: download and extract nats | ||||
|   tags: nats | ||||
|   ansible.builtin.unarchive: | ||||
|     src: "https://github.com/nats-io/nats-server/releases/download/v{{ nats_server_ver.stdout }}/nats-server-v{{ nats_server_ver.stdout }}-linux-amd64.tar.gz" | ||||
|     src: "https://github.com/nats-io/nats-server/releases/download/v{{ nats_server_ver.stdout }}/nats-server-v{{ nats_server_ver.stdout }}-linux-{{ goarch }}.tar.gz" | ||||
|     dest: "{{ nats_tmp.path }}" | ||||
|     remote_src: yes | ||||
|  | ||||
| @@ -211,7 +232,7 @@ | ||||
|   become: yes | ||||
|   ansible.builtin.copy: | ||||
|     remote_src: yes | ||||
|     src: "{{ nats_tmp.path }}/nats-server-v{{ nats_server_ver.stdout }}-linux-amd64/nats-server" | ||||
|     src: "{{ nats_tmp.path }}/nats-server-v{{ nats_server_ver.stdout }}-linux-{{ goarch }}/nats-server" | ||||
|     dest: /usr/local/bin/nats-server | ||||
|     owner: "{{ user }}" | ||||
|     group: "{{ user }}" | ||||
| @@ -227,7 +248,7 @@ | ||||
| - name: download nodejs setup | ||||
|   tags: nodejs | ||||
|   ansible.builtin.get_url: | ||||
|     url: https://deb.nodesource.com/setup_16.x | ||||
|     url: https://deb.nodesource.com/setup_18.x | ||||
|     dest: "{{ nodejs_tmp.path }}/setup_node.sh" | ||||
|     mode: "0755" | ||||
|  | ||||
| @@ -314,8 +335,8 @@ | ||||
| - name: add nginx repo | ||||
|   tags: nginx | ||||
|   become: yes | ||||
|   ansible.builtin.copy: | ||||
|     src: nginx.repo | ||||
|   ansible.builtin.template: | ||||
|     src: nginx.repo.j2 | ||||
|     dest: /etc/apt/sources.list.d/nginx.list | ||||
|     owner: "root" | ||||
|     group: "root" | ||||
| @@ -391,12 +412,16 @@ | ||||
|     enabled: yes | ||||
|     state: restarted | ||||
|  | ||||
| - name: set natsapi fact | ||||
|   ansible.builtin.set_fact: | ||||
|     natsapi: "{{ 'nats-api' if ansible_architecture == 'x86_64' else 'nats-api-arm64' }}" | ||||
|  | ||||
| - name: copy nats-api bin | ||||
|   tags: nats-api | ||||
|   become: yes | ||||
|   ansible.builtin.copy: | ||||
|     remote_src: yes | ||||
|     src: "{{ backend_dir }}/natsapi/bin/nats-api" | ||||
|     src: "{{ backend_dir }}/natsapi/bin/{{ natsapi }}" | ||||
|     dest: /usr/local/bin/nats-api | ||||
|     owner: "{{ user }}" | ||||
|     group: "{{ user }}" | ||||
| @@ -482,39 +507,6 @@ | ||||
|     - { src: nats-server.systemd.j2, dest: /etc/systemd/system/nats.service } | ||||
|     - { src: mesh.systemd.j2, dest: /etc/systemd/system/meshcentral.service } | ||||
|  | ||||
| - name: import mongodb repo signing key | ||||
|   tags: mongo | ||||
|   become: yes | ||||
|   ansible.builtin.apt_key: | ||||
|     url: https://www.mongodb.org/static/pgp/server-4.4.asc | ||||
|     state: present | ||||
|  | ||||
| - name: setup mongodb repo | ||||
|   tags: mongo | ||||
|   become: yes | ||||
|   ansible.builtin.copy: | ||||
|     content: "deb https://repo.mongodb.org/apt/debian buster/mongodb-org/4.4 main" | ||||
|     dest: /etc/apt/sources.list.d/mongodb-org-4.4.list | ||||
|     owner: root | ||||
|     group: root | ||||
|     mode: "0644" | ||||
|  | ||||
| - name: install mongodb | ||||
|   tags: mongo | ||||
|   become: yes | ||||
|   ansible.builtin.apt: | ||||
|     pkg: mongodb-org | ||||
|     state: present | ||||
|     update_cache: yes | ||||
|  | ||||
| - name: ensure mongodb enabled and started | ||||
|   tags: mongo | ||||
|   become: yes | ||||
|   ansible.builtin.service: | ||||
|     name: mongod | ||||
|     enabled: yes | ||||
|     state: started | ||||
|  | ||||
| - name: get mesh_ver | ||||
|   tags: mesh | ||||
|   ansible.builtin.shell: grep "^MESH_VER" {{ settings_file }} | awk -F'[= "]' '{print $5}' | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| { | ||||
|   "settings": { | ||||
|     "Cert": "{{ mesh }}", | ||||
|     "MongoDb": "mongodb://127.0.0.1:27017", | ||||
|     "MongoDbName": "meshcentral", | ||||
|     "WANonly": true, | ||||
|     "Minify": 1, | ||||
|     "Port": 4430, | ||||
| @@ -10,19 +8,25 @@ | ||||
|     "RedirPort": 800, | ||||
|     "AllowLoginToken": true, | ||||
|     "AllowFraming": true, | ||||
|     "AgentPong": 300, | ||||
|     "AgentPing": 35, | ||||
|     "AllowHighQualityDesktop": true, | ||||
|     "TlsOffload": "127.0.0.1", | ||||
|     "agentCoreDump": false, | ||||
|     "Compression": true, | ||||
|     "WsCompression": true, | ||||
|     "AgentWsCompression": true, | ||||
|     "MaxInvalidLogin": { "time": 5, "count": 5, "coolofftime": 30 } | ||||
|     "MaxInvalidLogin": { "time": 5, "count": 5, "coolofftime": 30 }, | ||||
|     "postgres": { | ||||
|       "user": "{{ mesh_db_user }}", | ||||
|       "password": "{{ mesh_db_passwd }}", | ||||
|       "port": "5432", | ||||
|       "host": "localhost" | ||||
|     } | ||||
|   }, | ||||
|   "domains": { | ||||
|     "": { | ||||
|       "Title": "Tactical RMM", | ||||
|       "Title2": "Tactical RMM", | ||||
|       "Title": "Tactical RMM Dev", | ||||
|       "Title2": "Tactical RMM Dev", | ||||
|       "NewAccounts": false, | ||||
|       "CertUrl": "https://{{ mesh }}:443/", | ||||
|       "GeoLocation": true, | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| [Unit] | ||||
| Description=MeshCentral Server | ||||
| After=network.target mongod.service nginx.service | ||||
| After=network.target postgresql.service nginx.service | ||||
|  | ||||
| [Service] | ||||
| Type=simple | ||||
|   | ||||
							
								
								
									
										2
									
								
								ansible/roles/trmm_dev/templates/nginx.repo.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								ansible/roles/trmm_dev/templates/nginx.repo.j2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| deb https://nginx.org/packages/debian/ {{ ansible_distribution_release }} nginx | ||||
| deb-src https://nginx.org/packages/debian/ {{ ansible_distribution_release }} nginx | ||||
| @@ -13,6 +13,8 @@ | ||||
|     mesh_password: "changeme" | ||||
|     db_user: "changeme" | ||||
|     db_passwd: "changeme" | ||||
|     mesh_db_user: "changeme" | ||||
|     mesh_db_passwd: "changeme" | ||||
|     django_secret: "changeme" | ||||
|     django_user: "changeme" | ||||
|     django_password: "changeme" | ||||
|   | ||||
| @@ -5,6 +5,8 @@ from rest_framework.serializers import ( | ||||
|     SerializerMethodField, | ||||
| ) | ||||
|  | ||||
| from tacticalrmm.helpers import get_webdomain | ||||
|  | ||||
| from .models import APIKey, Role, User | ||||
|  | ||||
|  | ||||
| @@ -61,7 +63,7 @@ class TOTPSetupSerializer(ModelSerializer): | ||||
|  | ||||
|     def get_qr_url(self, obj): | ||||
|         return pyotp.totp.TOTP(obj.totp_key).provisioning_uri( | ||||
|             obj.username, issuer_name="Tactical RMM" | ||||
|             obj.username, issuer_name=get_webdomain() | ||||
|         ) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,24 @@ | ||||
| from django.core.management.base import BaseCommand | ||||
|  | ||||
| from agents.models import Agent | ||||
| from tacticalrmm.constants import AGENT_DEFER | ||||
|  | ||||
|  | ||||
| class Command(BaseCommand): | ||||
|     def find_duplicates(self, lst): | ||||
|         return list(set([item for item in lst if lst.count(item) > 1])) | ||||
|  | ||||
|     def handle(self, *args, **kwargs): | ||||
|         for agent in Agent.objects.defer(*AGENT_DEFER).prefetch_related( | ||||
|             "custom_fields__field" | ||||
|         ): | ||||
|             if dupes := self.find_duplicates( | ||||
|                 [i.field.name for i in agent.custom_fields.all()] | ||||
|             ): | ||||
|                 for dupe in dupes: | ||||
|                     cf = list( | ||||
|                         agent.custom_fields.filter(field__name=dupe).order_by("id") | ||||
|                     ) | ||||
|                     to_delete = cf[:-1] | ||||
|                     for i in to_delete: | ||||
|                         i.delete() | ||||
| @@ -0,0 +1,17 @@ | ||||
| # Generated by Django 4.2.3 on 2023-07-18 01:15 | ||||
|  | ||||
| from django.db import migrations | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|     dependencies = [ | ||||
|         ("core", "0037_coresettings_open_ai_model_and_more"), | ||||
|         ("agents", "0056_alter_agent_time_zone"), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AlterUniqueTogether( | ||||
|             name="agentcustomfield", | ||||
|             unique_together={("agent", "field")}, | ||||
|         ), | ||||
|     ] | ||||
| @@ -1011,6 +1011,9 @@ class AgentCustomField(models.Model): | ||||
|         default=list, | ||||
|     ) | ||||
|  | ||||
|     class Meta: | ||||
|         unique_together = (("agent", "field"),) | ||||
|  | ||||
|     def __str__(self) -> str: | ||||
|         return self.field.name | ||||
|  | ||||
|   | ||||
| @@ -570,6 +570,13 @@ def install_agent(request): | ||||
|     from agents.utils import get_agent_url | ||||
|     from core.utils import token_is_valid | ||||
|  | ||||
|     insecure = getattr(settings, "TRMM_INSECURE", False) | ||||
|  | ||||
|     if insecure and request.data["installMethod"] in {"exe", "powershell"}: | ||||
|         return notify_error( | ||||
|             "Not available in insecure mode. Please use the 'Manual' method." | ||||
|         ) | ||||
|  | ||||
|     # TODO rework this ghetto validation hack | ||||
|     # https://github.com/amidaware/tacticalrmm/issues/1461 | ||||
|     try: | ||||
| @@ -672,6 +679,9 @@ def install_agent(request): | ||||
|             if int(request.data["power"]): | ||||
|                 cmd.append("--power") | ||||
|  | ||||
|             if insecure: | ||||
|                 cmd.append("--insecure") | ||||
|  | ||||
|             resp["cmd"] = " ".join(str(i) for i in cmd) | ||||
|         else: | ||||
|             install_flags.insert(0, f"sudo ./{inno}") | ||||
| @@ -680,6 +690,8 @@ def install_agent(request): | ||||
|             resp["cmd"] = ( | ||||
|                 dl + f" && chmod +x {inno} && " + " ".join(str(i) for i in cmd) | ||||
|             ) | ||||
|             if insecure: | ||||
|                 resp["cmd"] += " --insecure" | ||||
|  | ||||
|         resp["url"] = download_url | ||||
|  | ||||
|   | ||||
| @@ -25,12 +25,16 @@ class GetAddAlerts(APIView): | ||||
|     def patch(self, request): | ||||
|         # top 10 alerts for dashboard icon | ||||
|         if "top" in request.data.keys(): | ||||
|             alerts = Alert.objects.filter( | ||||
|                 resolved=False, snoozed=False, hidden=False | ||||
|             ).order_by("alert_time")[: int(request.data["top"])] | ||||
|             count = Alert.objects.filter( | ||||
|                 resolved=False, snoozed=False, hidden=False | ||||
|             ).count() | ||||
|             alerts = ( | ||||
|                 Alert.objects.filter_by_role(request.user) | ||||
|                 .filter(resolved=False, snoozed=False, hidden=False) | ||||
|                 .order_by("alert_time")[: int(request.data["top"])] | ||||
|             ) | ||||
|             count = ( | ||||
|                 Alert.objects.filter_by_role(request.user) | ||||
|                 .filter(resolved=False, snoozed=False, hidden=False) | ||||
|                 .count() | ||||
|             ) | ||||
|             return Response( | ||||
|                 { | ||||
|                     "alerts_count": count, | ||||
|   | ||||
| @@ -172,6 +172,31 @@ class TestCheckViews(TacticalTestCase): | ||||
|  | ||||
|         self.check_not_authenticated("post", url) | ||||
|  | ||||
|     def test_reset_all_checks_status(self): | ||||
|         # setup data | ||||
|         agent = baker.make_recipe("agents.agent") | ||||
|         check = baker.make_recipe("checks.diskspace_check", agent=agent) | ||||
|         baker.make("checks.CheckResult", assigned_check=check, agent=agent) | ||||
|         baker.make( | ||||
|             "checks.CheckHistory", | ||||
|             check_id=check.id, | ||||
|             agent_id=agent.agent_id, | ||||
|             _quantity=30, | ||||
|         ) | ||||
|         baker.make( | ||||
|             "checks.CheckHistory", | ||||
|             check_id=check.id, | ||||
|             agent_id=agent.agent_id, | ||||
|             _quantity=30, | ||||
|         ) | ||||
|  | ||||
|         url = f"{base_url}/{agent.agent_id}/resetall/" | ||||
|  | ||||
|         resp = self.client.post(url) | ||||
|         self.assertEqual(resp.status_code, 200) | ||||
|  | ||||
|         self.check_not_authenticated("post", url) | ||||
|  | ||||
|     def test_add_memory_check(self): | ||||
|         url = f"{base_url}/" | ||||
|         agent = baker.make_recipe("agents.agent") | ||||
|   | ||||
| @@ -6,6 +6,7 @@ urlpatterns = [ | ||||
|     path("", views.GetAddChecks.as_view()), | ||||
|     path("<int:pk>/", views.GetUpdateDeleteCheck.as_view()), | ||||
|     path("<int:pk>/reset/", views.ResetCheck.as_view()), | ||||
|     path("<agent:agent_id>/resetall/", views.ResetAllChecksStatus.as_view()), | ||||
|     path("<agent:agent_id>/run/", views.run_checks), | ||||
|     path("<int:pk>/history/", views.GetCheckHistory.as_view()), | ||||
|     path("<str:target>/<int:pk>/csbulkrun/", views.bulk_run_checks), | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import asyncio | ||||
| from datetime import datetime as dt | ||||
|  | ||||
| from django.db.models import Q | ||||
| from django.db.models import Prefetch, Q | ||||
| from django.shortcuts import get_object_or_404 | ||||
| from django.utils import timezone as djangotime | ||||
| from rest_framework.decorators import api_view, permission_classes | ||||
| @@ -13,7 +13,7 @@ from rest_framework.views import APIView | ||||
| from agents.models import Agent | ||||
| from alerts.models import Alert | ||||
| from automation.models import Policy | ||||
| from tacticalrmm.constants import CheckStatus, CheckType | ||||
| from tacticalrmm.constants import AGENT_DEFER, CheckStatus, CheckType | ||||
| from tacticalrmm.exceptions import NatsDown | ||||
| from tacticalrmm.helpers import notify_error | ||||
| from tacticalrmm.nats_utils import abulk_nats_command | ||||
| @@ -122,15 +122,54 @@ class ResetCheck(APIView): | ||||
|         result.save() | ||||
|  | ||||
|         # resolve any alerts that are open | ||||
|         alert = Alert.create_or_return_check_alert( | ||||
|         if alert := Alert.create_or_return_check_alert( | ||||
|             result.assigned_check, agent=result.agent, skip_create=True | ||||
|         ) | ||||
|         if alert: | ||||
|         ): | ||||
|             alert.resolve() | ||||
|  | ||||
|         return Response("The check status was reset") | ||||
|  | ||||
|  | ||||
| class ResetAllChecksStatus(APIView): | ||||
|     permission_classes = [IsAuthenticated, ChecksPerms] | ||||
|  | ||||
|     def post(self, request, agent_id): | ||||
|         agent = get_object_or_404( | ||||
|             Agent.objects.defer(*AGENT_DEFER) | ||||
|             .select_related( | ||||
|                 "policy", | ||||
|                 "policy__alert_template", | ||||
|                 "alert_template", | ||||
|             ) | ||||
|             .prefetch_related( | ||||
|                 Prefetch( | ||||
|                     "checkresults", | ||||
|                     queryset=CheckResult.objects.select_related("assigned_check"), | ||||
|                 ), | ||||
|                 "agentchecks", | ||||
|             ), | ||||
|             agent_id=agent_id, | ||||
|         ) | ||||
|  | ||||
|         if not _has_perm_on_agent(request.user, agent.agent_id): | ||||
|             raise PermissionDenied() | ||||
|  | ||||
|         for check in agent.get_checks_with_policies(): | ||||
|             try: | ||||
|                 result = check.check_result | ||||
|                 result.status = CheckStatus.PASSING | ||||
|                 result.save() | ||||
|                 if alert := Alert.create_or_return_check_alert( | ||||
|                     result.assigned_check, agent=agent, skip_create=True | ||||
|                 ): | ||||
|                     alert.resolve() | ||||
|             except: | ||||
|                 # check hasn't run yet, no check result entry | ||||
|                 continue | ||||
|  | ||||
|         return Response("All checks status were reset") | ||||
|  | ||||
|  | ||||
| class GetCheckHistory(APIView): | ||||
|     permission_classes = [IsAuthenticated, ChecksPerms] | ||||
|  | ||||
|   | ||||
| @@ -3,6 +3,7 @@ import re | ||||
| import uuid | ||||
| from contextlib import suppress | ||||
|  | ||||
| from django.conf import settings | ||||
| from django.db.models import Count, Exists, OuterRef, Prefetch, prefetch_related_objects | ||||
| from django.shortcuts import get_object_or_404 | ||||
| from django.utils import timezone as djangotime | ||||
| @@ -288,6 +289,9 @@ class AgentDeployment(APIView): | ||||
|         return Response(DeploymentSerializer(deps, many=True).data) | ||||
|  | ||||
|     def post(self, request): | ||||
|         if getattr(settings, "TRMM_INSECURE", False): | ||||
|             return notify_error("Not available in insecure mode") | ||||
|  | ||||
|         from accounts.models import User | ||||
|  | ||||
|         site = get_object_or_404(Site, pk=request.data["site"]) | ||||
| @@ -343,6 +347,9 @@ class GenerateAgent(APIView): | ||||
|     permission_classes = (AllowAny,) | ||||
|  | ||||
|     def get(self, request, uid): | ||||
|         if getattr(settings, "TRMM_INSECURE", False): | ||||
|             return notify_error("Not available in insecure mode") | ||||
|  | ||||
|         from tacticalrmm.utils import generate_winagent_exe | ||||
|  | ||||
|         try: | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| if [ $EUID -ne 0 ]; then | ||||
|   echo "ERROR: Must be run as root" | ||||
|   exit 1 | ||||
|     echo "ERROR: Must be run as root" | ||||
|     exit 1 | ||||
| fi | ||||
|  | ||||
| HAS_SYSTEMD=$(ps --no-headers -o comm 1) | ||||
| @@ -12,6 +12,16 @@ if [ "${HAS_SYSTEMD}" != 'systemd' ]; then | ||||
|     exit 1 | ||||
| fi | ||||
|  | ||||
| if [[ $DISPLAY ]]; then | ||||
|     echo "ERROR: Display detected. Installer only supports running headless, i.e from ssh." | ||||
|     echo "If you cannot ssh in then please run 'sudo systemctl isolate multi-user.target' to switch to a non-graphical user session and run the installer again." | ||||
|     exit 1 | ||||
| fi | ||||
|  | ||||
| DEBUG=0 | ||||
| INSECURE=0 | ||||
| NOMESH=0 | ||||
|  | ||||
| agentDL='agentDLChange' | ||||
| meshDL='meshDLChange' | ||||
|  | ||||
| @@ -37,15 +47,15 @@ deb=(ubuntu debian raspbian kali linuxmint) | ||||
| rhe=(fedora rocky centos rhel amzn arch opensuse) | ||||
|  | ||||
| set_locale_deb() { | ||||
| locale-gen "en_US.UTF-8" | ||||
| localectl set-locale LANG=en_US.UTF-8 | ||||
| . /etc/default/locale | ||||
|     locale-gen "en_US.UTF-8" | ||||
|     localectl set-locale LANG=en_US.UTF-8 | ||||
|     . /etc/default/locale | ||||
| } | ||||
|  | ||||
| set_locale_rhel() { | ||||
| localedef -c -i en_US -f UTF-8 en_US.UTF-8 > /dev/null 2>&1 | ||||
| localectl set-locale LANG=en_US.UTF-8 | ||||
| . /etc/locale.conf | ||||
|     localedef -c -i en_US -f UTF-8 en_US.UTF-8 >/dev/null 2>&1 | ||||
|     localectl set-locale LANG=en_US.UTF-8 | ||||
|     . /etc/locale.conf | ||||
| } | ||||
|  | ||||
| RemoveOldAgent() { | ||||
| @@ -67,8 +77,14 @@ RemoveOldAgent() { | ||||
|  | ||||
| InstallMesh() { | ||||
|     if [ -f /etc/os-release ]; then | ||||
|         distroID=$(. /etc/os-release; echo $ID) | ||||
|         distroIDLIKE=$(. /etc/os-release; echo $ID_LIKE) | ||||
|         distroID=$( | ||||
|             . /etc/os-release | ||||
|             echo $ID | ||||
|         ) | ||||
|         distroIDLIKE=$( | ||||
|             . /etc/os-release | ||||
|             echo $ID_LIKE | ||||
|         ) | ||||
|         if [[ " ${deb[*]} " =~ " ${distroID} " ]]; then | ||||
|             set_locale_deb | ||||
|         elif [[ " ${deb[*]} " =~ " ${distroIDLIKE} " ]]; then | ||||
| @@ -80,11 +96,9 @@ InstallMesh() { | ||||
|         fi | ||||
|     fi | ||||
|  | ||||
|     meshTmpDir=$(mktemp -d -t "mesh-XXXXXXXXX") | ||||
|     if [ $? -ne 0 ]; then | ||||
|         meshTmpDir='/root/meshtemp' | ||||
|         mkdir -p ${meshTmpDir} | ||||
|     fi | ||||
|     meshTmpDir='/root/meshtemp' | ||||
|     mkdir -p $meshTmpDir | ||||
|  | ||||
|     meshTmpBin="${meshTmpDir}/meshagent" | ||||
|     wget --no-check-certificate -q -O ${meshTmpBin} ${meshDL} | ||||
|     chmod +x ${meshTmpBin} | ||||
| @@ -101,8 +115,8 @@ RemoveMesh() { | ||||
|     fi | ||||
|  | ||||
|     if [ -f "${meshSysD}" ]; then | ||||
|         systemctl stop ${meshSvcName} > /dev/null 2>&1 | ||||
|         systemctl disable ${meshSvcName} > /dev/null 2>&1 | ||||
|         systemctl stop ${meshSvcName} >/dev/null 2>&1 | ||||
|         systemctl disable ${meshSvcName} >/dev/null 2>&1 | ||||
|         rm -f ${meshSysD} | ||||
|     fi | ||||
|  | ||||
| @@ -120,6 +134,19 @@ if [ $# -ne 0 ] && [ $1 == 'uninstall' ]; then | ||||
|     exit 0 | ||||
| fi | ||||
|  | ||||
| while [[ "$#" -gt 0 ]]; do | ||||
|     case $1 in | ||||
|     --debug) DEBUG=1 ;; | ||||
|     --insecure) INSECURE=1 ;; | ||||
|     --nomesh) NOMESH=1 ;; | ||||
|     *) | ||||
|         echo "ERROR: Unknown parameter: $1" | ||||
|         exit 1 | ||||
|         ;; | ||||
|     esac | ||||
|     shift | ||||
| done | ||||
|  | ||||
| RemoveOldAgent | ||||
|  | ||||
| echo "Downloading tactical agent..." | ||||
| @@ -132,7 +159,7 @@ chmod +x ${agentBin} | ||||
|  | ||||
| MESH_NODE_ID="" | ||||
|  | ||||
| if [ $# -ne 0 ] && [ $1 == '--nomesh' ]; then | ||||
| if [[ $NOMESH -eq 1 ]]; then | ||||
|     echo "Skipping mesh install" | ||||
| else | ||||
|     if [ -f "${meshSystemBin}" ]; then | ||||
| @@ -150,23 +177,28 @@ if [ ! -d "${agentBinPath}" ]; then | ||||
|     mkdir -p ${agentBinPath} | ||||
| fi | ||||
|  | ||||
| if [ $# -ne 0 ] && [ $1 == '--debug' ]; then | ||||
|     INSTALL_CMD="${agentBin} -m install -api ${apiURL} -client-id ${clientID} -site-id ${siteID} -agent-type ${agentType} -auth ${token} -log debug" | ||||
| else | ||||
|     INSTALL_CMD="${agentBin} -m install -api ${apiURL} -client-id ${clientID} -site-id ${siteID} -agent-type ${agentType} -auth ${token}" | ||||
| fi | ||||
| INSTALL_CMD="${agentBin} -m install -api ${apiURL} -client-id ${clientID} -site-id ${siteID} -agent-type ${agentType} -auth ${token}" | ||||
|  | ||||
| if [ "${MESH_NODE_ID}" != '' ]; then | ||||
|     INSTALL_CMD+=" -meshnodeid ${MESH_NODE_ID}" | ||||
|     INSTALL_CMD+=" --meshnodeid ${MESH_NODE_ID}" | ||||
| fi | ||||
|  | ||||
| if [[ $DEBUG -eq 1 ]]; then | ||||
|     INSTALL_CMD+=" --log debug" | ||||
| fi | ||||
|  | ||||
| if [[ $INSECURE -eq 1 ]]; then | ||||
|     INSTALL_CMD+=" --insecure" | ||||
| fi | ||||
|  | ||||
| if [ "${proxy}" != '' ]; then | ||||
|     INSTALL_CMD+=" -proxy ${proxy}" | ||||
|     INSTALL_CMD+=" --proxy ${proxy}" | ||||
| fi | ||||
|  | ||||
| eval ${INSTALL_CMD} | ||||
|  | ||||
| tacticalsvc="$(cat << EOF | ||||
| tacticalsvc="$( | ||||
|     cat <<EOF | ||||
| [Unit] | ||||
| Description=Tactical RMM Linux Agent | ||||
|  | ||||
| @@ -184,7 +216,7 @@ KillMode=process | ||||
| WantedBy=multi-user.target | ||||
| EOF | ||||
| )" | ||||
| echo "${tacticalsvc}" | tee ${agentSysD} > /dev/null | ||||
| echo "${tacticalsvc}" | tee ${agentSysD} >/dev/null | ||||
|  | ||||
| systemctl daemon-reload | ||||
| systemctl enable ${agentSvcName} | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import os | ||||
| from django.conf import settings | ||||
| from django.core.management.base import BaseCommand | ||||
|  | ||||
| from tacticalrmm.helpers import get_nats_ports | ||||
| from tacticalrmm.helpers import get_nats_internal_protocol, get_nats_ports | ||||
|  | ||||
|  | ||||
| class Command(BaseCommand): | ||||
| @@ -21,9 +21,10 @@ class Command(BaseCommand): | ||||
|             ssl = "disable" | ||||
|  | ||||
|         nats_std_port, _ = get_nats_ports() | ||||
|         proto = get_nats_internal_protocol() | ||||
|         config = { | ||||
|             "key": settings.SECRET_KEY, | ||||
|             "natsurl": f"tls://{settings.ALLOWED_HOSTS[0]}:{nats_std_port}", | ||||
|             "natsurl": f"{proto}://{settings.ALLOWED_HOSTS[0]}:{nats_std_port}", | ||||
|             "user": db["USER"], | ||||
|             "pass": db["PASSWORD"], | ||||
|             "host": db["HOST"], | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| from django.core.management import call_command | ||||
| from django.core.management.base import BaseCommand | ||||
|  | ||||
| from core.utils import clear_entire_cache | ||||
| @@ -10,3 +11,4 @@ class Command(BaseCommand): | ||||
|         self.stdout.write(self.style.WARNING("Cleaning the cache")) | ||||
|         clear_entire_cache() | ||||
|         self.stdout.write(self.style.SUCCESS("Cache was cleared!")) | ||||
|         call_command("fix_dupe_agent_customfields") | ||||
|   | ||||
| @@ -502,3 +502,27 @@ class TestCoreUtils(TacticalTestCase): | ||||
|             r, | ||||
|             "http://tactical-meshcentral:4443/meshagents?id=4&meshid=abc123&installflags=0", | ||||
|         ) | ||||
|  | ||||
|     @override_settings(TRMM_INSECURE=True) | ||||
|     def test_get_meshagent_url_insecure(self): | ||||
|         r = get_meshagent_url( | ||||
|             ident=MeshAgentIdent.DARWIN_UNIVERSAL, | ||||
|             plat="darwin", | ||||
|             mesh_site="https://mesh.example.com", | ||||
|             mesh_device_id="abc123", | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             r, | ||||
|             "http://mesh.example.com:4430/meshagents?id=abc123&installflags=2&meshinstall=10005", | ||||
|         ) | ||||
|  | ||||
|         r = get_meshagent_url( | ||||
|             ident=MeshAgentIdent.WIN64, | ||||
|             plat="windows", | ||||
|             mesh_site="https://mesh.example.com", | ||||
|             mesh_device_id="abc123", | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             r, | ||||
|             "http://mesh.example.com:4430/meshagents?id=4&meshid=abc123&installflags=0", | ||||
|         ) | ||||
|   | ||||
| @@ -88,8 +88,12 @@ def get_mesh_ws_url() -> str: | ||||
|     if settings.DOCKER_BUILD: | ||||
|         uri = f"{settings.MESH_WS_URL}/control.ashx?auth={token}" | ||||
|     else: | ||||
|         site = core.mesh_site.replace("https", "wss") | ||||
|         uri = f"{site}/control.ashx?auth={token}" | ||||
|         if getattr(settings, "TRMM_INSECURE", False): | ||||
|             site = core.mesh_site.replace("https", "ws") | ||||
|             uri = f"{site}:4430/control.ashx?auth={token}" | ||||
|         else: | ||||
|             site = core.mesh_site.replace("https", "wss") | ||||
|             uri = f"{site}/control.ashx?auth={token}" | ||||
|  | ||||
|     return uri | ||||
|  | ||||
| @@ -181,6 +185,8 @@ def get_meshagent_url( | ||||
| ) -> str: | ||||
|     if settings.DOCKER_BUILD: | ||||
|         base = settings.MESH_WS_URL.replace("ws://", "http://") | ||||
|     elif getattr(settings, "TRMM_INSECURE", False): | ||||
|         base = mesh_site.replace("https", "http") + ":4430" | ||||
|     else: | ||||
|         base = mesh_site | ||||
|  | ||||
|   | ||||
| @@ -1,39 +1,39 @@ | ||||
| adrf==0.1.1 | ||||
| asgiref==3.7.2 | ||||
| celery==5.3.1 | ||||
| certifi==2023.5.7 | ||||
| certifi==2023.7.22 | ||||
| cffi==1.15.1 | ||||
| channels==4.0.0 | ||||
| channels_redis==4.1.0 | ||||
| cryptography==41.0.1 | ||||
| cryptography==41.0.3 | ||||
| daphne==4.0.0 | ||||
| Django==4.2.3 | ||||
| django-cors-headers==4.1.0 | ||||
| Django==4.2.4 | ||||
| django-cors-headers==4.2.0 | ||||
| django-ipware==5.0.0 | ||||
| django-rest-knox==4.2.0 | ||||
| djangorestframework==3.14.0 | ||||
| drf-spectacular==0.26.3 | ||||
| drf-spectacular==0.26.4 | ||||
| hiredis==2.2.3 | ||||
| meshctrl==0.1.15 | ||||
| msgpack==1.0.5 | ||||
| nats-py==2.3.1 | ||||
| packaging==23.1 | ||||
| psutil==5.9.5 | ||||
| psycopg2-binary==2.9.6 | ||||
| psycopg[binary]==3.1.10 | ||||
| pycparser==2.21 | ||||
| pycryptodome==3.18.0 | ||||
| pyotp==2.8.0 | ||||
| pyparsing==3.1.0 | ||||
| pyotp==2.9.0 | ||||
| pyparsing==3.1.1 | ||||
| pytz==2023.3 | ||||
| qrcode==7.4.2 | ||||
| redis==4.5.5 | ||||
| requests==2.31.0 | ||||
| six==1.16.0 | ||||
| sqlparse==0.4.4 | ||||
| twilio==8.3.0 | ||||
| urllib3==2.0.3 | ||||
| uWSGI==2.0.21 | ||||
| twilio==8.5.0 | ||||
| urllib3==2.0.4 | ||||
| uWSGI==2.0.22 | ||||
| validators==0.20.0 | ||||
| vine==5.0.0 | ||||
| websockets==11.0.3 | ||||
| zipp==3.15.0 | ||||
| zipp==3.16.2 | ||||
|   | ||||
| @@ -65,6 +65,8 @@ class GetEditActionService(APIView): | ||||
|     # win service action | ||||
|     def post(self, request, agent_id, svcname): | ||||
|         agent = get_object_or_404(Agent, agent_id=agent_id) | ||||
|         if agent.is_posix: | ||||
|             return notify_error("Please use 'Recover Connection' instead.") | ||||
|         action = request.data["sv_action"] | ||||
|         data = { | ||||
|             "func": "winsvcaction", | ||||
|   | ||||
| @@ -42,6 +42,13 @@ def get_nats_ports() -> tuple[int, int]: | ||||
|     return nats_standard_port, nats_websocket_port | ||||
|  | ||||
|  | ||||
| def get_nats_internal_protocol() -> str: | ||||
|     if getattr(settings, "TRMM_INSECURE", False): | ||||
|         return "nats" | ||||
|  | ||||
|     return "tls" | ||||
|  | ||||
|  | ||||
| def date_is_in_past(*, datetime_obj: "datetime", agent_tz: str) -> bool: | ||||
|     """ | ||||
|     datetime_obj must be a naive datetime | ||||
| @@ -66,8 +73,9 @@ def rand_range(min: int, max: int) -> float: | ||||
|  | ||||
| def setup_nats_options() -> dict[str, Any]: | ||||
|     nats_std_port, _ = get_nats_ports() | ||||
|     proto = get_nats_internal_protocol() | ||||
|     opts = { | ||||
|         "servers": f"tls://{settings.ALLOWED_HOSTS[0]}:{nats_std_port}", | ||||
|         "servers": f"{proto}://{settings.ALLOWED_HOSTS[0]}:{nats_std_port}", | ||||
|         "user": "tacticalrmm", | ||||
|         "name": "trmm-django", | ||||
|         "password": settings.SECRET_KEY, | ||||
|   | ||||
| @@ -20,27 +20,27 @@ MAC_UNINSTALL = BASE_DIR / "core" / "mac_uninstall.sh" | ||||
| AUTH_USER_MODEL = "accounts.User" | ||||
|  | ||||
| # latest release | ||||
| TRMM_VERSION = "0.16.0" | ||||
| TRMM_VERSION = "0.16.4" | ||||
|  | ||||
| # https://github.com/amidaware/tacticalrmm-web | ||||
| WEB_VERSION = "0.101.25" | ||||
| WEB_VERSION = "0.101.29" | ||||
|  | ||||
| # bump this version everytime vue code is changed | ||||
| # to alert user they need to manually refresh their browser | ||||
| APP_VER = "0.0.182" | ||||
| APP_VER = "0.0.184" | ||||
|  | ||||
| # https://github.com/amidaware/rmmagent | ||||
| LATEST_AGENT_VER = "2.4.9" | ||||
| LATEST_AGENT_VER = "2.5.0" | ||||
|  | ||||
| MESH_VER = "1.1.6" | ||||
| MESH_VER = "1.1.9" | ||||
|  | ||||
| NATS_SERVER_VER = "2.9.19" | ||||
| NATS_SERVER_VER = "2.9.21" | ||||
|  | ||||
| # for the update script, bump when need to recreate venv | ||||
| PIP_VER = "37" | ||||
| PIP_VER = "38" | ||||
|  | ||||
| SETUPTOOLS_VER = "67.8.0" | ||||
| WHEEL_VER = "0.40.0" | ||||
| SETUPTOOLS_VER = "68.0.0" | ||||
| WHEEL_VER = "0.41.1" | ||||
|  | ||||
| AGENT_BASE_URL = "https://agents.tacticalrmm.com" | ||||
|  | ||||
|   | ||||
| @@ -34,7 +34,12 @@ from tacticalrmm.constants import ( | ||||
|     DebugLogType, | ||||
|     ScriptShell, | ||||
| ) | ||||
| from tacticalrmm.helpers import get_certs, get_nats_ports, notify_error | ||||
| from tacticalrmm.helpers import ( | ||||
|     get_certs, | ||||
|     get_nats_internal_protocol, | ||||
|     get_nats_ports, | ||||
|     notify_error, | ||||
| ) | ||||
|  | ||||
|  | ||||
| def generate_winagent_exe( | ||||
| @@ -204,10 +209,6 @@ def reload_nats() -> None: | ||||
|     nats_std_port, nats_ws_port = get_nats_ports() | ||||
|  | ||||
|     config = { | ||||
|         "tls": { | ||||
|             "cert_file": cert_file, | ||||
|             "key_file": key_file, | ||||
|         }, | ||||
|         "authorization": {"users": users}, | ||||
|         "max_payload": 67108864, | ||||
|         "port": nats_std_port,  # internal only | ||||
| @@ -217,6 +218,12 @@ def reload_nats() -> None: | ||||
|         }, | ||||
|     } | ||||
|  | ||||
|     if get_nats_internal_protocol() == "tls": | ||||
|         config["tls"] = { | ||||
|             "cert_file": cert_file, | ||||
|             "key_file": key_file, | ||||
|         } | ||||
|  | ||||
|     if "NATS_HTTP_PORT" in os.environ: | ||||
|         config["http_port"] = int(os.getenv("NATS_HTTP_PORT"))  # type: ignore | ||||
|     elif hasattr(settings, "NATS_HTTP_PORT"): | ||||
|   | ||||
							
								
								
									
										41
									
								
								backup.sh
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								backup.sh
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| SCRIPT_VERSION="25" | ||||
| SCRIPT_VERSION="29" | ||||
|  | ||||
| GREEN='\033[0;32m' | ||||
| YELLOW='\033[1;33m' | ||||
| @@ -16,7 +16,7 @@ fi | ||||
| if [[ $* == *--schedule* ]]; then | ||||
|     ( | ||||
|         crontab -l 2>/dev/null | ||||
|         echo "0 0 * * * /rmm/backup.sh --auto" | ||||
|         echo "0 0 * * * /rmm/backup.sh --auto > /dev/null 2>&1" | ||||
|     ) | crontab - | ||||
|  | ||||
|     if [ ! -d /rmmbackups ]; then | ||||
| @@ -49,6 +49,10 @@ if [ -d /meshcentral/meshcentral-backup ]; then | ||||
|     rm -rf /meshcentral/meshcentral-backup/* | ||||
| fi | ||||
|  | ||||
| if [ -d /meshcentral/meshcentral-backups ]; then | ||||
|     rm -rf /meshcentral/meshcentral-backups/* | ||||
| fi | ||||
|  | ||||
| if [ -d /meshcentral/meshcentral-coredumps ]; then | ||||
|     rm -f /meshcentral/meshcentral-coredumps/* | ||||
| fi | ||||
| @@ -68,24 +72,41 @@ mkdir ${tmp_dir}/confd | ||||
| POSTGRES_USER=$(/rmm/api/env/bin/python /rmm/api/tacticalrmm/manage.py get_config dbuser) | ||||
| POSTGRES_PW=$(/rmm/api/env/bin/python /rmm/api/tacticalrmm/manage.py get_config dbpw) | ||||
|  | ||||
| pg_dump --dbname=postgresql://"${POSTGRES_USER}":"${POSTGRES_PW}"@127.0.0.1:5432/tacticalrmm | gzip -9 >${tmp_dir}/postgres/db-${dt_now}.psql.gz | ||||
| pg_dump --dbname=postgresql://"${POSTGRES_USER}":"${POSTGRES_PW}"@localhost:5432/tacticalrmm | gzip -9 >${tmp_dir}/postgres/db-${dt_now}.psql.gz | ||||
|  | ||||
| node /meshcentral/node_modules/meshcentral --dbexport # for import to postgres | ||||
|  | ||||
| if grep -q postgres "/meshcentral/meshcentral-data/config.json"; then | ||||
|     if ! which jq >/dev/null; then | ||||
|         sudo apt-get install -y jq >null | ||||
|         sudo apt-get install -y jq >/dev/null | ||||
|     fi | ||||
|     MESH_POSTGRES_USER=$(jq '.settings.postgres.user' /meshcentral/meshcentral-data/config.json -r) | ||||
|     MESH_POSTGRES_PW=$(jq '.settings.postgres.password' /meshcentral/meshcentral-data/config.json -r) | ||||
|     pg_dump --dbname=postgresql://"${MESH_POSTGRES_USER}":"${MESH_POSTGRES_PW}"@127.0.0.1:5432/meshcentral | gzip -9 >${tmp_dir}/postgres/mesh-db-${dt_now}.psql.gz | ||||
|     pg_dump --dbname=postgresql://"${MESH_POSTGRES_USER}":"${MESH_POSTGRES_PW}"@localhost:5432/meshcentral | gzip -9 >${tmp_dir}/postgres/mesh-db-${dt_now}.psql.gz | ||||
| else | ||||
|     mongodump --gzip --out=${tmp_dir}/meshcentral/mongo | ||||
| fi | ||||
|  | ||||
| tar -czvf ${tmp_dir}/meshcentral/mesh.tar.gz --exclude=/meshcentral/node_modules /meshcentral | ||||
|  | ||||
| sudo tar -czvf ${tmp_dir}/certs/etc-letsencrypt.tar.gz -C /etc/letsencrypt . | ||||
| if [ -d /etc/letsencrypt ]; then | ||||
|     sudo tar -czvf ${tmp_dir}/certs/etc-letsencrypt.tar.gz -C /etc/letsencrypt . | ||||
| fi | ||||
|  | ||||
| local_settings='/rmm/api/tacticalrmm/tacticalrmm/local_settings.py' | ||||
|  | ||||
| if grep -q CERT_FILE "$local_settings"; then | ||||
|     mkdir -p ${tmp_dir}/certs/custom | ||||
|     CERT_FILE=$(grep "^CERT_FILE" "$local_settings" | awk -F'[= "]' '{print $5}') | ||||
|     KEY_FILE=$(grep "^KEY_FILE" "$local_settings" | awk -F'[= "]' '{print $5}') | ||||
|     cp -p $CERT_FILE ${tmp_dir}/certs/custom/cert | ||||
|     cp -p $KEY_FILE ${tmp_dir}/certs/custom/key | ||||
| elif grep -q TRMM_INSECURE "$local_settings"; then | ||||
|     mkdir -p ${tmp_dir}/certs/selfsigned | ||||
|     certdir='/etc/ssl/tactical' | ||||
|     cp -p ${certdir}/key.pem ${tmp_dir}/certs/selfsigned/ | ||||
|     cp -p ${certdir}/cert.pem ${tmp_dir}/certs/selfsigned/ | ||||
| fi | ||||
|  | ||||
| for i in rmm frontend meshcentral; do | ||||
|     sudo cp /etc/nginx/sites-available/${i}.conf ${tmp_dir}/nginx/ | ||||
| @@ -95,7 +116,7 @@ sudo tar -czvf ${tmp_dir}/confd/etc-confd.tar.gz -C /etc/conf.d . | ||||
|  | ||||
| sudo cp ${sysd}/rmm.service ${sysd}/celery.service ${sysd}/celerybeat.service ${sysd}/meshcentral.service ${sysd}/nats.service ${sysd}/daphne.service ${sysd}/nats-api.service ${tmp_dir}/systemd/ | ||||
|  | ||||
| cp /rmm/api/tacticalrmm/tacticalrmm/local_settings.py ${tmp_dir}/rmm/ | ||||
| cp $local_settings ${tmp_dir}/rmm/ | ||||
|  | ||||
| if [[ $* == *--auto* ]]; then | ||||
|  | ||||
| @@ -114,9 +135,9 @@ if [[ $* == *--auto* ]]; then | ||||
|  | ||||
|     rm -rf ${tmp_dir} | ||||
|  | ||||
|     find /rmmbackups/daily/ -maxdepth 1 -mtime +14 -type d -exec rm -rv {} \; | ||||
|     find /rmmbackups/weekly/ -maxdepth 1 -mtime +60 -type d -exec rm -rv {} \; | ||||
|     find /rmmbackups/monthly/ -maxdepth 1 -mtime +380 -type d -exec rm -rv {} \; | ||||
|     find /rmmbackups/daily/ -type f -mtime +14 -name '*.tar' -execdir rm -- '{}' \; | ||||
|     find /rmmbackups/weekly/ -type f -mtime +60 -name '*.tar' -execdir rm -- '{}' \; | ||||
|     find /rmmbackups/monthly/ -type f -mtime +380 -name '*.tar' -execdir rm -- '{}' \; | ||||
|     echo -ne "${GREEN}Backup Completed${NC}\n" | ||||
|     exit | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| FROM nats:2.9.19-alpine | ||||
| FROM nats:2.9.20-alpine | ||||
|  | ||||
| ENV TACTICAL_DIR /opt/tactical | ||||
| ENV TACTICAL_READY_FILE ${TACTICAL_DIR}/tmp/tactical.ready | ||||
|   | ||||
| @@ -14,17 +14,17 @@ SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"] | ||||
|  | ||||
| COPY api/tacticalrmm/requirements.txt ${TACTICAL_TMP_DIR}/api/requirements.txt | ||||
|  | ||||
| RUN apt-get update && | ||||
|     apt-get install -y --no-install-recommends gcc libc6-dev && | ||||
|     pip install --upgrade pip && | ||||
|     pip install --no-cache-dir setuptools wheel && | ||||
| RUN apt-get update && \ | ||||
|     apt-get install -y --no-install-recommends gcc libc6-dev && \ | ||||
|     pip install --upgrade pip && \ | ||||
|     pip install --no-cache-dir setuptools wheel && \ | ||||
|     pip install --no-cache-dir -r ${TACTICAL_TMP_DIR}/api/requirements.txt | ||||
|  | ||||
| # pulls community scripts from git repo | ||||
| FROM python:3.11.4-slim AS GET_SCRIPTS_STAGE | ||||
|  | ||||
| RUN apt-get update && | ||||
|     apt-get install -y --no-install-recommends git && | ||||
| RUN apt-get update && \ | ||||
|     apt-get install -y --no-install-recommends git && \ | ||||
|     git clone https://github.com/amidaware/community-scripts.git /community-scripts | ||||
|  | ||||
| # runtime image | ||||
| @@ -46,11 +46,11 @@ COPY --from=GET_SCRIPTS_STAGE /community-scripts ${TACTICAL_TMP_DIR}/community-s | ||||
| COPY --from=CREATE_VENV_STAGE ${VIRTUAL_ENV} ${VIRTUAL_ENV} | ||||
|  | ||||
| # install deps | ||||
| RUN apt-get update && | ||||
|     apt-get upgrade -y && | ||||
|     apt-get install -y --no-install-recommends rsync && | ||||
|     rm -rf /var/lib/apt/lists/* && | ||||
|     groupadd -g 1000 "${TACTICAL_USER}" && | ||||
| RUN apt-get update && \ | ||||
|     apt-get upgrade -y && \ | ||||
|     apt-get install -y --no-install-recommends rsync && \ | ||||
|     rm -rf /var/lib/apt/lists/* && \ | ||||
|     groupadd -g 1000 "${TACTICAL_USER}" && \ | ||||
|     useradd -M -d "${TACTICAL_DIR}" -s /bin/bash -u 1000 -g 1000 "${TACTICAL_USER}" | ||||
|  | ||||
| SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"] | ||||
|   | ||||
							
								
								
									
										14
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								go.mod
									
									
									
									
									
								
							| @@ -6,21 +6,21 @@ require ( | ||||
| 	github.com/golang/protobuf v1.5.2 // indirect | ||||
| 	github.com/jmoiron/sqlx v1.3.5 | ||||
| 	github.com/lib/pq v1.10.9 | ||||
| 	github.com/nats-io/nats-server/v2 v2.9.18 // indirect | ||||
| 	github.com/nats-io/nats.go v1.27.0 | ||||
| 	github.com/nats-io/nats-server/v2 v2.9.21 // indirect | ||||
| 	github.com/nats-io/nats.go v1.28.0 | ||||
| 	github.com/ugorji/go/codec v1.2.11 | ||||
| 	github.com/wh1te909/trmm-shared v0.0.0-20220227075846-f9f757361139 | ||||
| 	google.golang.org/protobuf v1.28.0 // indirect | ||||
| ) | ||||
|  | ||||
| require github.com/sirupsen/logrus v1.9.0 | ||||
| require github.com/sirupsen/logrus v1.9.3 | ||||
|  | ||||
| require ( | ||||
| 	github.com/klauspost/compress v1.16.5 // indirect | ||||
| 	github.com/klauspost/compress v1.16.7 // indirect | ||||
| 	github.com/nats-io/nkeys v0.4.4 // indirect | ||||
| 	github.com/nats-io/nuid v1.0.1 // indirect | ||||
| 	github.com/stretchr/testify v1.7.1 // indirect | ||||
| 	golang.org/x/crypto v0.9.0 // indirect | ||||
| 	golang.org/x/sys v0.8.0 // indirect | ||||
| 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect | ||||
| 	golang.org/x/crypto v0.11.0 // indirect | ||||
| 	golang.org/x/sys v0.10.0 // indirect | ||||
| 	gopkg.in/yaml.v3 v3.0.1 // indirect | ||||
| ) | ||||
|   | ||||
							
								
								
									
										26
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								go.sum
									
									
									
									
									
								
							| @@ -9,8 +9,8 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu | ||||
| github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= | ||||
| github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= | ||||
| github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= | ||||
| github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= | ||||
| github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= | ||||
| github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= | ||||
| github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= | ||||
| github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= | ||||
| github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= | ||||
| @@ -18,10 +18,10 @@ github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRU | ||||
| github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= | ||||
| github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= | ||||
| github.com/nats-io/jwt/v2 v2.4.1 h1:Y35W1dgbbz2SQUYDPCaclXcuqleVmpbRa7646Jf2EX4= | ||||
| github.com/nats-io/nats-server/v2 v2.9.18 h1:00muGH0qu/7NAw1b/2eFcpIvdHcTghj6PFjUVhy8zEo= | ||||
| github.com/nats-io/nats-server/v2 v2.9.18/go.mod h1:aTb/xtLCGKhfTFLxP591CMWfkdgBmcUUSkiSOe5A3gw= | ||||
| github.com/nats-io/nats.go v1.27.0 h1:3o9fsPhmoKm+yK7rekH2GtWoE+D9jFbw8N3/ayI1C00= | ||||
| github.com/nats-io/nats.go v1.27.0/go.mod h1:XpbWUlOElGwTYbMR7imivs7jJj9GtK7ypv321Wp6pjc= | ||||
| github.com/nats-io/nats-server/v2 v2.9.21 h1:2TBTh0UDE74eNXQmV4HofsmRSCiVN0TH2Wgrp6BD6fk= | ||||
| github.com/nats-io/nats-server/v2 v2.9.21/go.mod h1:ozqMZc2vTHcNcblOiXMWIXkf8+0lDGAi5wQcG+O1mHU= | ||||
| github.com/nats-io/nats.go v1.28.0 h1:Th4G6zdsz2d0OqXdfzKLClo6bOfoI/b1kInhRtFIy5c= | ||||
| github.com/nats-io/nats.go v1.28.0/go.mod h1:XpbWUlOElGwTYbMR7imivs7jJj9GtK7ypv321Wp6pjc= | ||||
| github.com/nats-io/nkeys v0.4.4 h1:xvBJ8d69TznjcQl9t6//Q5xXuVhyYiSos6RPtvQNTwA= | ||||
| github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64= | ||||
| github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= | ||||
| @@ -30,6 +30,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb | ||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||
| github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= | ||||
| github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= | ||||
| github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= | ||||
| github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= | ||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= | ||||
| @@ -38,11 +40,11 @@ github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4d | ||||
| github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= | ||||
| github.com/wh1te909/trmm-shared v0.0.0-20220227075846-f9f757361139 h1:PfOl03o+Y+svWrfXAAu1QWUDePu1yqTq0pf4rpnN8eA= | ||||
| github.com/wh1te909/trmm-shared v0.0.0-20220227075846-f9f757361139/go.mod h1:ILUz1utl5KgwrxmNHv0RpgMtKeh8gPAABvK2MiXBqv8= | ||||
| golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= | ||||
| golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= | ||||
| golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= | ||||
| golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= | ||||
| golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= | ||||
| golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= | ||||
| golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= | ||||
| @@ -51,5 +53,5 @@ google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscL | ||||
| google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||
| gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= | ||||
| gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||
| gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||||
| gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||
|   | ||||
							
								
								
									
										86
									
								
								install.sh
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								install.sh
									
									
									
									
									
								
							| @@ -1,9 +1,9 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| SCRIPT_VERSION="74" | ||||
| SCRIPT_VERSION="77" | ||||
| SCRIPT_URL='https://raw.githubusercontent.com/amidaware/tacticalrmm/master/install.sh' | ||||
|  | ||||
| sudo apt install -y curl wget dirmngr gnupg lsb-release | ||||
| sudo apt install -y curl wget dirmngr gnupg lsb-release ca-certificates | ||||
|  | ||||
| GREEN='\033[0;32m' | ||||
| YELLOW='\033[1;33m' | ||||
| @@ -14,6 +14,7 @@ NC='\033[0m' | ||||
| SCRIPTS_DIR='/opt/trmm-community-scripts' | ||||
| PYTHON_VER='3.11.4' | ||||
| SETTINGS_FILE='/rmm/api/tacticalrmm/tacticalrmm/settings.py' | ||||
| local_settings='/rmm/api/tacticalrmm/tacticalrmm/local_settings.py' | ||||
|  | ||||
| TMP_FILE=$(mktemp -p "" "rmminstall_XXXXXXXXXX") | ||||
| curl -s -L "${SCRIPT_URL}" >${TMP_FILE} | ||||
| @@ -137,6 +138,12 @@ while [[ $letsemail != *[@]*[.]* ]]; do | ||||
|   read letsemail | ||||
| done | ||||
|  | ||||
| if grep -q manage_etc_hosts /etc/hosts; then | ||||
|   sudo sed -i '/manage_etc_hosts: true/d' /etc/cloud/cloud.cfg >/dev/null | ||||
|   echo -e "\nmanage_etc_hosts: false" | sudo tee --append /etc/cloud/cloud.cfg >/dev/null | ||||
|   sudo systemctl restart cloud-init >/dev/null | ||||
| fi | ||||
|  | ||||
| CHECK_HOSTS=$(grep 127.0.1.1 /etc/hosts | grep "$rmmdomain" | grep "$meshdomain" | grep "$frontenddomain") | ||||
| HAS_11=$(grep 127.0.1.1 /etc/hosts) | ||||
|  | ||||
| @@ -155,19 +162,38 @@ if echo "$IPV4" | grep -qE '^(10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|192 | ||||
|   BEHIND_NAT=true | ||||
| fi | ||||
|  | ||||
| insecure=false | ||||
| if [[ $* == *--insecure* ]]; then | ||||
|   insecure=true | ||||
| fi | ||||
|  | ||||
| sudo apt install -y software-properties-common | ||||
| sudo apt update | ||||
| sudo apt install -y certbot openssl | ||||
| sudo apt install -y openssl | ||||
|  | ||||
| print_green 'Getting wildcard cert' | ||||
| if [[ "$insecure" = true ]]; then | ||||
|   print_green 'Generating self-signed cert' | ||||
|   certdir='/etc/ssl/tactical' | ||||
|   sudo mkdir -p $certdir | ||||
|   sudo chown ${USER}:${USER} $certdir | ||||
|   sudo chmod 770 $certdir | ||||
|   CERT_PRIV_KEY=${certdir}/key.pem | ||||
|   CERT_PUB_KEY=${certdir}/cert.pem | ||||
|   openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 \ | ||||
|     -nodes -keyout ${CERT_PRIV_KEY} -out ${CERT_PUB_KEY} -subj "/CN=${rootdomain}" \ | ||||
|     -addext "subjectAltName=DNS:${rootdomain},DNS:*.${rootdomain}" | ||||
|  | ||||
| else | ||||
|   sudo apt install -y certbot | ||||
|   print_green 'Getting wildcard cert' | ||||
|  | ||||
| sudo certbot certonly --manual -d *.${rootdomain} --agree-tos --no-bootstrap --preferred-challenges dns -m ${letsemail} --no-eff-email | ||||
| while [[ $? -ne 0 ]]; do | ||||
|   sudo certbot certonly --manual -d *.${rootdomain} --agree-tos --no-bootstrap --preferred-challenges dns -m ${letsemail} --no-eff-email | ||||
| done | ||||
|  | ||||
| CERT_PRIV_KEY=/etc/letsencrypt/live/${rootdomain}/privkey.pem | ||||
| CERT_PUB_KEY=/etc/letsencrypt/live/${rootdomain}/fullchain.pem | ||||
|   while [[ $? -ne 0 ]]; do | ||||
|     sudo certbot certonly --manual -d *.${rootdomain} --agree-tos --no-bootstrap --preferred-challenges dns -m ${letsemail} --no-eff-email | ||||
|   done | ||||
|   CERT_PRIV_KEY=/etc/letsencrypt/live/${rootdomain}/privkey.pem | ||||
|   CERT_PUB_KEY=/etc/letsencrypt/live/${rootdomain}/fullchain.pem | ||||
| fi | ||||
|  | ||||
| sudo chown ${USER}:${USER} -R /etc/letsencrypt | ||||
|  | ||||
| @@ -226,7 +252,10 @@ done | ||||
|  | ||||
| print_green 'Installing NodeJS' | ||||
|  | ||||
| curl -sL https://deb.nodesource.com/setup_18.x | sudo -E bash - | ||||
| sudo mkdir -p /etc/apt/keyrings | ||||
| curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg | ||||
| NODE_MAJOR=18 | ||||
| echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list | ||||
| sudo apt update | ||||
| sudo apt install -y gcc g++ make | ||||
| sudo apt install -y nodejs | ||||
| @@ -247,7 +276,7 @@ cd ~ | ||||
| sudo rm -rf Python-${PYTHON_VER} Python-${PYTHON_VER}.tgz | ||||
|  | ||||
| print_green 'Installing redis and git' | ||||
| sudo apt install -y ca-certificates redis git | ||||
| sudo apt install -y redis git | ||||
|  | ||||
| print_green 'Installing postgresql' | ||||
|  | ||||
| @@ -330,9 +359,23 @@ MESH_VER=$(grep "^MESH_VER" "$SETTINGS_FILE" | awk -F'[= "]' '{print $5}') | ||||
| sudo mkdir -p /meshcentral/meshcentral-data | ||||
| sudo chown ${USER}:${USER} -R /meshcentral | ||||
| cd /meshcentral | ||||
| npm install meshcentral@${MESH_VER} | ||||
| sudo chown ${USER}:${USER} -R /meshcentral | ||||
|  | ||||
| mesh_pkg="$( | ||||
|   cat <<EOF | ||||
| { | ||||
|   "dependencies": { | ||||
|     "archiver": "5.3.1", | ||||
|     "meshcentral": "${MESH_VER}", | ||||
|     "otplib": "10.2.3", | ||||
|     "pg": "8.7.1", | ||||
|     "pgtools": "0.3.2" | ||||
|   } | ||||
| } | ||||
| EOF | ||||
| )" | ||||
| echo "${mesh_pkg}" >/meshcentral/package.json | ||||
|  | ||||
| meshcfg="$( | ||||
|   cat <<EOF | ||||
| { | ||||
| @@ -376,6 +419,8 @@ EOF | ||||
| )" | ||||
| echo "${meshcfg}" >/meshcentral/meshcentral-data/config.json | ||||
|  | ||||
| npm install | ||||
|  | ||||
| localvars="$( | ||||
|   cat <<EOF | ||||
| SECRET_KEY = "${DJANGO_SEKRET}" | ||||
| @@ -407,7 +452,11 @@ REDIS_HOST    = "localhost" | ||||
| ADMIN_ENABLED = True | ||||
| EOF | ||||
| )" | ||||
| echo "${localvars}" >/rmm/api/tacticalrmm/tacticalrmm/local_settings.py | ||||
| echo "${localvars}" >$local_settings | ||||
|  | ||||
| if [[ "$insecure" = true ]]; then | ||||
|   echo "TRMM_INSECURE = True" | tee --append $local_settings >/dev/null | ||||
| fi | ||||
|  | ||||
| if [ "$arch" = "x86_64" ]; then | ||||
|   natsapi='nats-api' | ||||
| @@ -440,7 +489,7 @@ python manage.py load_community_scripts | ||||
| WEB_VERSION=$(python manage.py get_config webversion) | ||||
| printf >&2 "${YELLOW}%0.s*${NC}" {1..80} | ||||
| printf >&2 "\n" | ||||
| printf >&2 "${YELLOW}Please create your login for the RMM website and django admin${NC}\n" | ||||
| printf >&2 "${YELLOW}Please create your login for the RMM website${NC}\n" | ||||
| printf >&2 "${YELLOW}%0.s*${NC}" {1..80} | ||||
| printf >&2 "\n" | ||||
| echo -ne "Username: " | ||||
| @@ -850,7 +899,7 @@ done | ||||
| sleep 5 | ||||
| sudo systemctl enable meshcentral | ||||
|  | ||||
| print_green 'Starting meshcentral and waiting for it to install plugins' | ||||
| print_green 'Starting meshcentral and waiting for it to be ready' | ||||
|  | ||||
| sudo systemctl restart meshcentral | ||||
|  | ||||
| @@ -874,7 +923,7 @@ meshtoken="$( | ||||
| MESH_TOKEN_KEY = "${MESHTOKENKEY}" | ||||
| EOF | ||||
| )" | ||||
| echo "${meshtoken}" | tee --append /rmm/api/tacticalrmm/tacticalrmm/local_settings.py >/dev/null | ||||
| echo "${meshtoken}" | tee --append $local_settings >/dev/null | ||||
|  | ||||
| print_green 'Creating meshcentral account and group' | ||||
|  | ||||
| @@ -911,7 +960,7 @@ sudo systemctl enable nats-api.service | ||||
| sudo systemctl start nats-api.service | ||||
|  | ||||
| ## disable django admin | ||||
| sed -i 's/ADMIN_ENABLED = True/ADMIN_ENABLED = False/g' /rmm/api/tacticalrmm/tacticalrmm/local_settings.py | ||||
| sed -i 's/ADMIN_ENABLED = True/ADMIN_ENABLED = False/g' $local_settings | ||||
|  | ||||
| print_green 'Restarting services' | ||||
| for i in rmm.service daphne.service celery.service celerybeat.service; do | ||||
| @@ -923,7 +972,6 @@ printf >&2 "${YELLOW}%0.s*${NC}" {1..80} | ||||
| printf >&2 "\n\n" | ||||
| printf >&2 "${YELLOW}Installation complete!${NC}\n\n" | ||||
| printf >&2 "${YELLOW}Access your rmm at: ${GREEN}https://${frontenddomain}${NC}\n\n" | ||||
| printf >&2 "${YELLOW}Django admin url (disabled by default): ${GREEN}https://${rmmdomain}/${ADMINURL}/${NC}\n\n" | ||||
| printf >&2 "${YELLOW}MeshCentral username: ${GREEN}${meshusername}${NC}\n" | ||||
| printf >&2 "${YELLOW}MeshCentral password: ${GREEN}${MESHPASSWD}${NC}\n\n" | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								main.go
									
									
									
									
									
								
							| @@ -12,7 +12,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	version = "3.4.7" | ||||
| 	version = "3.4.8" | ||||
| 	log     = logrus.New() | ||||
| ) | ||||
|  | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										61
									
								
								restore.sh
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								restore.sh
									
									
									
									
									
								
							| @@ -1,10 +1,10 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| SCRIPT_VERSION="49" | ||||
| SCRIPT_VERSION="52" | ||||
| SCRIPT_URL='https://raw.githubusercontent.com/amidaware/tacticalrmm/master/restore.sh' | ||||
|  | ||||
| sudo apt update | ||||
| sudo apt install -y curl wget dirmngr gnupg lsb-release | ||||
| sudo apt install -y curl wget dirmngr gnupg lsb-release ca-certificates | ||||
|  | ||||
| GREEN='\033[0;32m' | ||||
| YELLOW='\033[1;33m' | ||||
| @@ -122,7 +122,10 @@ sudo apt update | ||||
|  | ||||
| print_green 'Installing NodeJS' | ||||
|  | ||||
| curl -sL https://deb.nodesource.com/setup_18.x | sudo -E bash - | ||||
| sudo mkdir -p /etc/apt/keyrings | ||||
| curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg | ||||
| NODE_MAJOR=18 | ||||
| echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list | ||||
| sudo apt update | ||||
| sudo apt install -y gcc g++ make | ||||
| sudo apt install -y nodejs | ||||
| @@ -193,10 +196,30 @@ sudo apt install -y certbot openssl | ||||
|  | ||||
| print_green 'Restoring certs' | ||||
|  | ||||
| sudo rm -rf /etc/letsencrypt | ||||
| sudo mkdir /etc/letsencrypt | ||||
| sudo tar -xzf $tmp_dir/certs/etc-letsencrypt.tar.gz -C /etc/letsencrypt | ||||
| sudo chown ${USER}:${USER} -R /etc/letsencrypt | ||||
| if [ -f "$tmp_dir/certs/etc-letsencrypt.tar.gz" ]; then | ||||
|   sudo rm -rf /etc/letsencrypt | ||||
|   sudo mkdir /etc/letsencrypt | ||||
|   sudo tar -xzf $tmp_dir/certs/etc-letsencrypt.tar.gz -C /etc/letsencrypt | ||||
|   sudo chown ${USER}:${USER} -R /etc/letsencrypt | ||||
| fi | ||||
|  | ||||
| if [ -d "${tmp_dir}/certs/custom" ]; then | ||||
|   CERT_FILE=$(grep "^CERT_FILE" "$tmp_dir/rmm/local_settings.py" | awk -F'[= "]' '{print $5}') | ||||
|   KEY_FILE=$(grep "^KEY_FILE" "$tmp_dir/rmm/local_settings.py" | awk -F'[= "]' '{print $5}') | ||||
|  | ||||
|   sudo mkdir -p $(dirname $CERT_FILE) $(dirname $KEY_FILE) | ||||
|   sudo chown ${USER}:${USER} $(dirname $CERT_FILE) $(dirname $KEY_FILE) | ||||
|  | ||||
|   cp -p ${tmp_dir}/certs/custom/cert $CERT_FILE | ||||
|   cp -p ${tmp_dir}/certs/custom/key $KEY_FILE | ||||
| elif [ -d "${tmp_dir}/certs/selfsigned" ]; then | ||||
|   certdir='/etc/ssl/tactical' | ||||
|   sudo mkdir -p $certdir | ||||
|   sudo chown ${USER}:${USER} $certdir | ||||
|   sudo chmod 770 $certdir | ||||
|   cp -p ${tmp_dir}/certs/selfsigned/key.pem $certdir | ||||
|   cp -p ${tmp_dir}/certs/selfsigned/cert.pem $certdir | ||||
| fi | ||||
|  | ||||
| print_green 'Restoring celery configs' | ||||
|  | ||||
| @@ -224,7 +247,7 @@ cd ~ | ||||
| sudo rm -rf Python-${PYTHON_VER} Python-${PYTHON_VER}.tgz | ||||
|  | ||||
| print_green 'Installing redis and git' | ||||
| sudo apt install -y ca-certificates redis git | ||||
| sudo apt install -y redis git | ||||
|  | ||||
| print_green 'Installing postgresql' | ||||
|  | ||||
| @@ -335,7 +358,21 @@ else | ||||
| fi | ||||
|  | ||||
| cd /meshcentral | ||||
| npm install meshcentral@${MESH_VER} | ||||
| mesh_pkg="$( | ||||
|   cat <<EOF | ||||
| { | ||||
|   "dependencies": { | ||||
|     "archiver": "5.3.1", | ||||
|     "meshcentral": "${MESH_VER}", | ||||
|     "otplib": "10.2.3", | ||||
|     "pg": "8.7.1", | ||||
|     "pgtools": "0.3.2" | ||||
|   } | ||||
| } | ||||
| EOF | ||||
| )" | ||||
| echo "${mesh_pkg}" >/meshcentral/package.json | ||||
| npm install | ||||
|  | ||||
| if [ "$FROM_MONGO" = true ]; then | ||||
|   node node_modules/meshcentral --dbimport >/dev/null | ||||
| @@ -396,6 +433,12 @@ deactivate | ||||
|  | ||||
| print_green 'Restoring hosts file' | ||||
|  | ||||
| if grep -q manage_etc_hosts /etc/hosts; then | ||||
|   sudo sed -i '/manage_etc_hosts: true/d' /etc/cloud/cloud.cfg >/dev/null | ||||
|   echo -e "\nmanage_etc_hosts: false" | sudo tee --append /etc/cloud/cloud.cfg >/dev/null | ||||
|   sudo systemctl restart cloud-init >/dev/null | ||||
| fi | ||||
|  | ||||
| HAS_11=$(grep 127.0.1.1 /etc/hosts) | ||||
| if [[ $HAS_11 ]]; then | ||||
|   sudo sed -i "/127.0.1.1/s/$/ ${API} ${webdomain} ${meshdomain}/" /etc/hosts | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
| # v1.1 1/21/2022 update to include all services | ||||
| # v 1.2 6/24/2023 changed to add date, easier readability and ipv4 addresses only for checks | ||||
|  | ||||
| # This script asks for the 3 subdomains, checks they exist, checks they resolve locally and remotely (using google dns for remote),  | ||||
| # This script asks for the 3 subdomains, checks they exist, checks they resolve locally and remotely (using google dns for remote), | ||||
| # checks services are running, checks ports are opened. The only part that will make the script stop is if the sub domains dont exist, theres literally no point in going further if thats the case | ||||
|  | ||||
| GREEN='\033[0;32m' | ||||
| @@ -17,113 +17,111 @@ NC='\033[0m' | ||||
| now=$(date) | ||||
| echo -e -------------- $now -------------- | tee -a checklog.log | ||||
|  | ||||
| osname=$(lsb_release -si) | ||||
| osname=${osname^} | ||||
| osname=$(echo "$osname" | tr '[A-Z]' '[a-z]') | ||||
| relno=$(lsb_release -sr | cut -d. -f1) | ||||
|  | ||||
| # Resolve Locally used DNS server | ||||
| resolvestatus=$(systemctl is-active systemd-resolved.service) | ||||
| if [ $resolvestatus = active ]; then | ||||
|     locdns=$(resolvectl | grep -m 1 -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+') | ||||
|     echo -e $locdns | ||||
| if [[ "$osname" == "debian" && "$relno" == 12 ]]; then | ||||
| 	locdns=$(resolvconf -l | tail -n +1 | grep -m 1 -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+') | ||||
|  | ||||
| elif [ $resolvestatus = active ]; then | ||||
| 	locdns=$(resolvectl | tail -n +1 | grep -m 1 -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+') | ||||
| else | ||||
| 	while ! [[ $resolveconf ]]; do | ||||
|     resolveconf=$(sudo systemctl status systemd-resolved.service | grep "Active: active (running)") | ||||
|     sudo systemctl start systemd-resolved.service | ||||
|     echo -ne "DNS Resolver not ready yet...${NC}\n" | ||||
|     sleep 3 | ||||
| done | ||||
|     locdns=$(resolvectl | grep -m 1 -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+') | ||||
|     echo -e $locdns | ||||
|     sudo systemctl stop systemd-resolved.service | ||||
| fi  | ||||
|  | ||||
| while [[ $rmmdomain != *[.]*[.]* ]] | ||||
| do | ||||
| echo -e "${YELLOW}Enter the subdomain for the backend (e.g. api.example.com)${NC}: " | ||||
| read rmmdomain | ||||
| done | ||||
|  | ||||
| if ping -c 1 $rmmdomain &> /dev/null | ||||
| then | ||||
|     echo -e ${GREEN} Verified $rmmdomain | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
|   echo -e ${RED} $rmmdomain doesnt exist please create it or check for a typo | tee -a checklog.log | ||||
|   printf >&2 "\n\n" | ||||
|   printf >&2 "You will have a log file called checklog.log in the directory you ran this script from\n\n" | ||||
|   printf >&2 "\n\n" | ||||
|   exit | ||||
| 		resolveconf=$(sudo systemctl status systemd-resolved.service | grep "Active: active (running)") | ||||
| 		sudo systemctl start systemd-resolved.service | ||||
| 		echo -ne "DNS Resolver not ready yet...${NC}\n" | ||||
| 		sleep 3 | ||||
| 	done | ||||
| 	locdns=$(resolvectl | tail -n +1 | grep -m 1 -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+') | ||||
| 	sudo systemctl stop systemd-resolved.service | ||||
| fi | ||||
|  | ||||
| while [[ $frontenddomain != *[.]*[.]* ]] | ||||
| do | ||||
| echo -e "${YELLOW}Enter the subdomain for the frontend (e.g. rmm.example.com)${NC}: " | ||||
| read frontenddomain | ||||
| while [[ $rmmdomain != *[.]*[.]* ]]; do | ||||
| 	echo -e "${YELLOW}Enter the subdomain for the backend (e.g. api.example.com)${NC}: " | ||||
| 	read rmmdomain | ||||
| done | ||||
|  | ||||
| if ping -c 1 $frontenddomain &> /dev/null | ||||
| then | ||||
|     echo -e ${GREEN} Verified $frontenddomain | tee -a checklog.log | ||||
| if ping -c 1 $rmmdomain &>/dev/null; then | ||||
| 	echo -e ${GREEN} Verified $rmmdomain | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
|   echo -e ${RED} $frontenddomain doesnt exist please create it or check for a typo | tee -a checklog.log | ||||
|   printf >&2 "\n\n" | ||||
|   printf >&2 "You will have a log file called checklog.log in the directory you ran this script from\n\n" | ||||
|   printf >&2 "\n\n" | ||||
|   exit | ||||
| 	echo -e ${RED} $rmmdomain doesnt exist please create it or check for a typo | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| 	printf >&2 "You will have a log file called checklog.log in the directory you ran this script from\n\n" | ||||
| 	printf >&2 "\n\n" | ||||
| 	exit | ||||
| fi | ||||
|  | ||||
| while [[ $meshdomain != *[.]*[.]* ]] | ||||
| do | ||||
| echo -e "${YELLOW}Enter the subdomain for meshcentral (e.g. mesh.example.com)${NC}: " | ||||
| read meshdomain | ||||
| while [[ $frontenddomain != *[.]*[.]* ]]; do | ||||
| 	echo -e "${YELLOW}Enter the subdomain for the frontend (e.g. rmm.example.com)${NC}: " | ||||
| 	read frontenddomain | ||||
| done | ||||
|  | ||||
| if ping -c 1 $meshdomain &> /dev/null | ||||
| then | ||||
|     echo -e ${GREEN} Verified $meshdomain | tee -a checklog.log | ||||
| if ping -c 1 $frontenddomain &>/dev/null; then | ||||
| 	echo -e ${GREEN} Verified $frontenddomain | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
|   echo -e ${RED} $meshdomain doesnt exist please create it or check for a typo | tee -a checklog.log | ||||
|   printf >&2 "\n\n" | tee -a checklog.log | ||||
|   printf >&2 "You will have a log file called checklog.log in the directory you ran this script from\n\n" | ||||
|   printf >&2 "\n\n" | ||||
|   exit | ||||
| 	echo -e ${RED} $frontenddomain doesnt exist please create it or check for a typo | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| 	printf >&2 "You will have a log file called checklog.log in the directory you ran this script from\n\n" | ||||
| 	printf >&2 "\n\n" | ||||
| 	exit | ||||
| fi | ||||
|  | ||||
| while [[ $domain != *[.]* ]] | ||||
| do | ||||
| echo -e "${YELLOW}Enter yourdomain used for letsencrypt (e.g. example.com)${NC}: " | ||||
| read domain | ||||
| while [[ $meshdomain != *[.]*[.]* ]]; do | ||||
| 	echo -e "${YELLOW}Enter the subdomain for meshcentral (e.g. mesh.example.com)${NC}: " | ||||
| 	read meshdomain | ||||
| done | ||||
|  | ||||
| 	echo -e ${YELLOW} Checking IPs | tee -a checklog.log  | ||||
| if ping -c 1 $meshdomain &>/dev/null; then | ||||
| 	echo -e ${GREEN} Verified $meshdomain | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
| 	echo -e ${RED} $meshdomain doesnt exist please create it or check for a typo | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
| 	printf >&2 "You will have a log file called checklog.log in the directory you ran this script from\n\n" | ||||
| 	printf >&2 "\n\n" | ||||
| 	exit | ||||
| fi | ||||
|  | ||||
| while [[ $domain != *[.]* ]]; do | ||||
| 	echo -e "${YELLOW}Enter yourdomain used for letsencrypt (e.g. example.com)${NC}: " | ||||
| 	read domain | ||||
| done | ||||
|  | ||||
| echo -e ${YELLOW} Checking IPs | tee -a checklog.log | ||||
| printf >&2 "\n\n" | ||||
|  | ||||
| # Check rmmdomain IPs | ||||
| locapiip=$(dig @"$locdns" +short $rmmdomain | grep -m 1 -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+') | ||||
| remapiip=$(dig @8.8.8.8 +short $rmmdomain | grep -m 1 -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+') | ||||
|  | ||||
| if [ "$locapiip" = "$remapiip" ]; then | ||||
|     echo -e ${GREEN} Success $rmmdomain is Locally Resolved: "$locapiip"  Remotely Resolved: "$remapiip" | tee -a checklog.log | ||||
| 	echo -e ${GREEN} Success $rmmdomain is Locally Resolved: "$locapiip" Remotely Resolved: "$remapiip" | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
| 	echo -e ${RED} Locally Resolved: "$locapiip"  Remotely Resolved: "$remapiip" | tee -a checklog.log | ||||
| 	echo -e ${RED} Locally Resolved: "$locapiip" Remotely Resolved: "$remapiip" | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
|     echo -e ${RED} Your Local and Remote IP for $rmmdomain all agents will require non-public DNS to find TRMM server | tee -a checklog.log | ||||
| 	echo -e ${RED} Your Local and Remote IP for $rmmdomain all agents will require non-public DNS to find TRMM server | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
|  | ||||
| fi | ||||
|  | ||||
|  | ||||
| # Check Frontenddomain IPs | ||||
| locrmmip=$(dig @"$locdns" +short $frontenddomain | grep -m 1 -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+') | ||||
| remrmmip=$(dig @8.8.8.8 +short $frontenddomain | grep -m 1 -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+') | ||||
|  | ||||
| if [ "$locrmmip" = "$remrmmip" ]; then | ||||
|     echo -e ${GREEN} Success $frontenddomain is Locally Resolved: "$locrmmip"  Remotely Resolved: "$remrmmip"| tee -a checklog.log | ||||
| 	echo -e ${GREEN} Success $frontenddomain is Locally Resolved: "$locrmmip" Remotely Resolved: "$remrmmip" | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
| 	echo -e ${RED}  Locally Resolved: "$locrmmip"  Remotely Resolved: "$remrmmip" | tee -a checklog.log | ||||
| 	echo -e ${RED} Locally Resolved: "$locrmmip" Remotely Resolved: "$remrmmip" | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
|     echo -e ${RED} echo Your Local and Remote IP for $frontenddomain all agents will require non-public DNS to find TRMM server | tee -a checklog.log | ||||
| 	echo -e ${RED} echo Your Local and Remote IP for $frontenddomain all agents will require non-public DNS to find TRMM server | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
|  | ||||
| fi | ||||
| @@ -133,18 +131,18 @@ locmeship=$(dig @"$locdns" +short $meshdomain | grep -m 1 -oE '[0-9]+\.[0-9]+\.[ | ||||
| remmeship=$(dig @8.8.8.8 +short $meshdomain | grep -m 1 -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+') | ||||
|  | ||||
| if [ "$locmeship" = "$remmeship" ]; then | ||||
|     echo -e ${GREEN} Success $meshdomain is Locally Resolved: "$locmeship"  Remotely Resolved: "$remmeship" | tee -a checklog.log | ||||
| 	echo -e ${GREEN} Success $meshdomain is Locally Resolved: "$locmeship" Remotely Resolved: "$remmeship" | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
| else | ||||
| 	echo -e ${RED} Locally Resolved: "$locmeship"  Remotely Resolved: "$remmeship" | tee -a checklog.log | ||||
|     printf >&2 "\n\n" | tee -a checklog.log | ||||
|     echo -e ${RED} Your Local and Remote IP for $meshdomain all agents will require non-public DNS to find TRMM server | tee -a checklog.log | ||||
| 	echo -e ${RED} Locally Resolved: "$locmeship" Remotely Resolved: "$remmeship" | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
| 	echo -e ${RED} Your Local and Remote IP for $meshdomain all agents will require non-public DNS to find TRMM server | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
|  | ||||
| fi | ||||
|  | ||||
| 	echo -e ${YELLOW} Checking Services | tee -a checklog.log  | ||||
| 	printf >&2 "\n\n" | ||||
| echo -e ${YELLOW} Checking Services | tee -a checklog.log | ||||
| printf >&2 "\n\n" | ||||
|  | ||||
| # Check if services are running | ||||
| rmmstatus=$(systemctl is-active rmm) | ||||
| @@ -161,127 +159,128 @@ redisserverstatus=$(systemctl is-active redis-server) | ||||
|  | ||||
| # RMM Service | ||||
| if [ $rmmstatus = active ]; then | ||||
|     echo -e ${GREEN} Success RMM Service is Running | tee -a checklog.log | ||||
| 	echo -e ${GREEN} Success RMM Service is Running | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
|     echo -e ${RED}  'RMM Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	echo -e ${RED} 'RMM Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
|  | ||||
| fi | ||||
|  | ||||
| # daphne Service | ||||
| if [ $daphnestatus = active ]; then | ||||
|     echo -e ${GREEN} Success daphne Service is Running | tee -a checklog.log | ||||
| 	echo -e ${GREEN} Success daphne Service is Running | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
|     echo -e ${RED}  'daphne Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	echo -e ${RED} 'daphne Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
|  | ||||
| fi | ||||
|  | ||||
| # celery Service | ||||
| if [ $celerystatus = active ]; then | ||||
|     echo -e ${GREEN} Success celery Service is Running | tee -a checklog.log | ||||
| 	echo -e ${GREEN} Success celery Service is Running | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
|     echo -e ${RED}  'celery Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	echo -e ${RED} 'celery Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
|  | ||||
| fi | ||||
|  | ||||
| # celerybeat Service | ||||
| if [ $celerybeatstatus = active ]; then | ||||
|     echo -e ${GREEN} Success celerybeat Service is Running | tee -a checklog.log | ||||
| 	echo -e ${GREEN} Success celerybeat Service is Running | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
|     echo -e ${RED}  'celerybeat Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	echo -e ${RED} 'celerybeat Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
|  | ||||
| fi | ||||
|  | ||||
| # nginx Service | ||||
| if [ $nginxstatus = active ]; then | ||||
|     echo -e ${GREEN} Success nginx Service is Running | tee -a checklog.log | ||||
| 	echo -e ${GREEN} Success nginx Service is Running | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
|     echo -e ${RED}  'nginx Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	echo -e ${RED} 'nginx Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
|  | ||||
| fi | ||||
|  | ||||
| # nats Service | ||||
| if [ $natsstatus = active ]; then | ||||
|     echo -e ${GREEN} Success nats Service is running | tee -a checklog.log | ||||
| 	echo -e ${GREEN} Success nats Service is running | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
|     echo -e ${RED}  'nats Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	echo -e ${RED} 'nats Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
|  | ||||
| fi | ||||
|  | ||||
| # nats-api Service | ||||
| if [ $natsapistatus = active ]; then | ||||
|     echo -e ${GREEN} Success nats-api Service is running | tee -a checklog.log | ||||
| 	echo -e ${GREEN} Success nats-api Service is running | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
|     echo -e ${RED}  'nats-api Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	echo -e ${RED} 'nats-api Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
|  | ||||
| fi | ||||
|  | ||||
| # meshcentral Service | ||||
| if [ $meshcentralstatus = active ]; then | ||||
|     echo -e ${GREEN} Success meshcentral Service is running | tee -a checklog.log | ||||
| 	echo -e ${GREEN} Success meshcentral Service is running | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
|     echo -e ${RED}  'meshcentral Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	echo -e ${RED} 'meshcentral Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
|  | ||||
| fi | ||||
|  | ||||
| # mongod Service | ||||
| if [ $mongodstatus = active ]; then | ||||
|     echo -e ${GREEN} Success mongod Service is running | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
|     echo -e ${RED}  'mongod Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| if grep -q mongo "/meshcentral/meshcentral-data/config.json"; then | ||||
| 	if [ $mongodstatus = active ]; then | ||||
| 		echo -e ${GREEN} Success mongod Service is running | tee -a checklog.log | ||||
| 		printf >&2 "\n\n" | ||||
| 	else | ||||
| 		printf >&2 "\n\n" | tee -a checklog.log | ||||
| 		echo -e ${RED} 'mongod Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 		printf >&2 "\n\n" | ||||
|  | ||||
| 	fi | ||||
| fi | ||||
|  | ||||
| # postgresql Service | ||||
| if [ $postgresqlstatus = active ]; then | ||||
|     echo -e ${GREEN} Success postgresql Service is running | tee -a checklog.log | ||||
| 	echo -e ${GREEN} Success postgresql Service is running | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
|     echo -e ${RED}  'postgresql Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	echo -e ${RED} 'postgresql Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
|  | ||||
| fi | ||||
|  | ||||
| # redis-server Service | ||||
| if [ $redisserverstatus = active ]; then | ||||
|     echo -e ${GREEN} Success redis-server Service is running | tee -a checklog.log | ||||
| 	echo -e ${GREEN} Success redis-server Service is running | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
| 	printf >&2 "\n\n" | tee -a checklog.log | ||||
|     echo -e ${RED}  'redis-server Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	echo -e ${RED} 'redis-server Service isnt running (Tactical wont work without this)' | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
|  | ||||
| fi | ||||
|  | ||||
| 	echo -e ${YELLOW} Checking Open Ports | tee -a checklog.log  | ||||
| 	printf >&2 "\n\n" | ||||
| echo -e ${YELLOW} Checking Open Ports | tee -a checklog.log | ||||
| printf >&2 "\n\n" | ||||
|  | ||||
| #Get WAN IP | ||||
| wanip=$(dig @resolver4.opendns.com myip.opendns.com +short) | ||||
| @@ -289,73 +288,72 @@ wanip=$(dig @resolver4.opendns.com myip.opendns.com +short) | ||||
| echo -e ${GREEN} WAN IP is $wanip | tee -a checklog.log | ||||
| printf >&2 "\n\n" | ||||
|  | ||||
| if ! which nc >/dev/null | ||||
| then | ||||
|     echo "netcat is not installed, installing now" | ||||
|     sudo apt-get install netcat -y | ||||
| if ! which nc >/dev/null; then | ||||
| 	echo "netcat is not installed, installing now" | ||||
| 	sudo apt-get install netcat -y | ||||
| fi | ||||
|  | ||||
| #Check if HTTPs Port is open | ||||
| if ( nc -zv $wanip 443 2>&1 >/dev/null ); then | ||||
|     echo -e ${GREEN} 'HTTPs Port is open' | tee -a checklog.log | ||||
| if (nc -zv $wanip 443 2>&1 >/dev/null); then | ||||
| 	echo -e ${GREEN} 'HTTPs Port is open' | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
|     echo -e ${RED} 'HTTPs port is closed (you may want this if running locally only)' | tee -a checklog.log | ||||
| 	echo -e ${RED} 'HTTPs port is closed (you may want this if running locally only)' | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| fi | ||||
|  | ||||
| 	echo -e ${YELLOW} Checking For Proxy | tee -a checklog.log  | ||||
| 	printf >&2 "\n\n" | ||||
| 	echo -e ${YELLOW} ......this might take a while!! | ||||
| 	printf >&2 "\n\n" | ||||
| echo -e ${YELLOW} Checking For Proxy | tee -a checklog.log | ||||
| printf >&2 "\n\n" | ||||
| echo -e ${YELLOW} ......this might take a while!! | ||||
| printf >&2 "\n\n" | ||||
|  | ||||
| # Detect Proxy via cert | ||||
| proxyext=$(openssl s_client -showcerts -servername $remapiip -connect $remapiip:443 2>/dev/null | openssl x509 -inform pem -noout -text) | ||||
| proxyint=$(openssl s_client -showcerts -servername 127.0.0.1 -connect 127.0.0.1:443 2>/dev/null | openssl x509 -inform pem -noout -text) | ||||
|  | ||||
| if [[ $proxyext == $proxyint ]]; then | ||||
|     echo -e ${GREEN} No Proxy detected using Certificate | tee -a checklog.log | ||||
| 	echo -e ${GREEN} No Proxy detected using Certificate | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
|     echo -e ${RED} Proxy detected using Certificate | tee -a checklog.log | ||||
| 	echo -e ${RED} Proxy detected using Certificate | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| fi | ||||
|  | ||||
| # Detect Proxy via IP | ||||
| if [ $wanip != $remrmmip ]; then | ||||
|     echo -e ${RED} Proxy detected using IP | tee -a checklog.log | ||||
| 	echo -e ${RED} Proxy detected using IP | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| else | ||||
|     echo -e ${GREEN} No Proxy detected using IP | tee -a checklog.log | ||||
| 	echo -e ${GREEN} No Proxy detected using IP | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| fi | ||||
|  | ||||
| 	echo -e ${YELLOW} Checking SSL Certificate is up to date | tee -a checklog.log  | ||||
| 	printf >&2 "\n\n" | ||||
| echo -e ${YELLOW} Checking SSL Certificate is up to date | tee -a checklog.log | ||||
| printf >&2 "\n\n" | ||||
|  | ||||
| #SSL Certificate check | ||||
| cert=$(sudo certbot certificates) | ||||
|  | ||||
| if [[ "$cert" != *"INVALID"* ]]; then | ||||
|     echo -e ${GREEN} SSL Certificate for $domain is fine  | tee -a checklog.log | ||||
| 	echo -e ${GREEN} SSL Certificate for $domain is fine | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
|  | ||||
| else | ||||
|     echo -e ${RED} SSL Certificate has expired or doesnt exist for $domain  | tee -a checklog.log | ||||
| 	echo -e ${RED} SSL Certificate has expired or doesnt exist for $domain | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| fi | ||||
|  | ||||
| # Get List of Certbot Certificates | ||||
| sudo certbot certificates | tee -a checklog.log | ||||
|  | ||||
| 	echo -e ${YELLOW} Getting summary output of logs | tee -a checklog.log   | ||||
| echo -e ${YELLOW} Getting summary output of logs | tee -a checklog.log | ||||
|  | ||||
| tail /rmm/api/tacticalrmm/tacticalrmm/private/log/django_debug.log  | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| tail /rmm/api/tacticalrmm/tacticalrmm/private/log/error.log  | tee -a checklog.log | ||||
| 	printf >&2 "\n\n" | ||||
| tail /rmm/api/tacticalrmm/tacticalrmm/private/log/django_debug.log | tee -a checklog.log | ||||
| printf >&2 "\n\n" | ||||
| tail /rmm/api/tacticalrmm/tacticalrmm/private/log/error.log | tee -a checklog.log | ||||
| printf >&2 "\n\n" | ||||
|  | ||||
| printf >&2 "\n\n" | ||||
| echo -e ${YELLOW}  | ||||
| echo -e ${YELLOW} | ||||
| printf >&2 "You will have a log file called checklog.log in the directory you ran this script from\n\n" | ||||
| echo -e ${NC} | ||||
|   | ||||
							
								
								
									
										41
									
								
								update.sh
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								update.sh
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| SCRIPT_VERSION="145" | ||||
| SCRIPT_VERSION="147" | ||||
| SCRIPT_URL='https://raw.githubusercontent.com/amidaware/tacticalrmm/master/update.sh' | ||||
| LATEST_SETTINGS_URL='https://raw.githubusercontent.com/amidaware/tacticalrmm/master/api/tacticalrmm/tacticalrmm/settings.py' | ||||
| YELLOW='\033[1;33m' | ||||
| @@ -357,8 +357,29 @@ python manage.py clear_redis_celery_locks | ||||
| python manage.py post_update_tasks | ||||
| API=$(python manage.py get_config api) | ||||
| WEB_VERSION=$(python manage.py get_config webversion) | ||||
| FRONTEND=$(python manage.py get_config webdomain) | ||||
| MESHDOMAIN=$(python manage.py get_config meshdomain) | ||||
| deactivate | ||||
|  | ||||
| if grep -q manage_etc_hosts /etc/hosts; then | ||||
|   sudo sed -i '/manage_etc_hosts: true/d' /etc/cloud/cloud.cfg >/dev/null | ||||
|   if ! grep -q "manage_etc_hosts: false" /etc/cloud/cloud.cfg; then | ||||
|     echo -e "\nmanage_etc_hosts: false" | sudo tee --append /etc/cloud/cloud.cfg >/dev/null | ||||
|     sudo systemctl restart cloud-init >/dev/null | ||||
|   fi | ||||
| fi | ||||
|  | ||||
| CHECK_HOSTS=$(grep 127.0.1.1 /etc/hosts | grep "$API" | grep "$FRONTEND" | grep "$MESHDOMAIN") | ||||
| HAS_11=$(grep 127.0.1.1 /etc/hosts) | ||||
|  | ||||
| if ! [[ $CHECK_HOSTS ]]; then | ||||
|   if [[ $HAS_11 ]]; then | ||||
|     sudo sed -i "/127.0.1.1/s/$/ ${API} ${FRONTEND} ${MESHDOMAIN}/" /etc/hosts | ||||
|   else | ||||
|     echo "127.0.1.1 ${API} ${FRONTEND} ${MESHDOMAIN}" | sudo tee --append /etc/hosts >/dev/null | ||||
|   fi | ||||
| fi | ||||
|  | ||||
| if [ -d /rmm/web ]; then | ||||
|   rm -rf /rmm/web | ||||
| fi | ||||
| @@ -386,8 +407,22 @@ if [[ "${CURRENT_MESH_VER}" != "${LATEST_MESH_VER}" ]] || [[ "$force" = true ]]; | ||||
|   sudo systemctl stop meshcentral | ||||
|   sudo chown ${USER}:${USER} -R /meshcentral | ||||
|   cd /meshcentral | ||||
|   rm -rf node_modules/ | ||||
|   npm install meshcentral@${LATEST_MESH_VER} | ||||
|   rm -rf node_modules/ package.json package-lock.json | ||||
|   mesh_pkg="$( | ||||
|     cat <<EOF | ||||
| { | ||||
|   "dependencies": { | ||||
|     "archiver": "5.3.1", | ||||
|     "meshcentral": "${LATEST_MESH_VER}", | ||||
|     "otplib": "10.2.3", | ||||
|     "pg": "8.7.1", | ||||
|     "pgtools": "0.3.2" | ||||
|   } | ||||
| } | ||||
| EOF | ||||
|   )" | ||||
|   echo "${mesh_pkg}" >/meshcentral/package.json | ||||
|   npm install | ||||
|   sudo systemctl start meshcentral | ||||
| fi | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user