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 | ||||
|   | ||||
| @@ -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 | ||||
| 		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 [[ $rmmdomain != *[.]*[.]* ]] | ||||
| do | ||||
| echo -e "${YELLOW}Enter the subdomain for the backend (e.g. api.example.com)${NC}: " | ||||
| read rmmdomain | ||||
| 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 | ||||
| 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 | ||||
| 	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 [[ $frontenddomain != *[.]*[.]* ]] | ||||
| do | ||||
| echo -e "${YELLOW}Enter the subdomain for the frontend (e.g. rmm.example.com)${NC}: " | ||||
| read frontenddomain | ||||
| 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 $frontenddomain &> /dev/null | ||||
| then | ||||
|     echo -e ${GREEN} Verified $frontenddomain | 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} $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} $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 [[ $meshdomain != *[.]*[.]* ]] | ||||
| do | ||||
| echo -e "${YELLOW}Enter the subdomain for meshcentral (e.g. mesh.example.com)${NC}: " | ||||
| read meshdomain | ||||
| while [[ $meshdomain != *[.]*[.]* ]]; do | ||||
| 	echo -e "${YELLOW}Enter the subdomain for meshcentral (e.g. mesh.example.com)${NC}: " | ||||
| 	read meshdomain | ||||
| done | ||||
|  | ||||
| if ping -c 1 $meshdomain &> /dev/null | ||||
| then | ||||
|     echo -e ${GREEN} Verified $meshdomain | 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 | ||||
| 	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 | ||||
| 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" | ||||
| 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,71 +288,70 @@ 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} | ||||
|   | ||||
							
								
								
									
										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