From d00c00fc34d86a2de81b2331dbd0798f96f31ea8 Mon Sep 17 00:00:00 2001 From: Arjun Hemrajani Date: Wed, 25 Mar 2026 15:43:21 +0530 Subject: [PATCH] Add signoz. --- docker-install.sh | 7 + erpnext-systemd/install-erpnext-systemd.sh | 34 +++ headscale/headscale-install.sh | 324 +++++++++++++++++++++ signoz/domain-signoz.sh | 53 ++++ signoz/install-signoz.sh | 46 +++ 5 files changed, 464 insertions(+) create mode 100644 docker-install.sh create mode 100644 erpnext-systemd/install-erpnext-systemd.sh create mode 100644 headscale/headscale-install.sh create mode 100644 signoz/domain-signoz.sh create mode 100644 signoz/install-signoz.sh diff --git a/docker-install.sh b/docker-install.sh new file mode 100644 index 0000000..278ce0f --- /dev/null +++ b/docker-install.sh @@ -0,0 +1,7 @@ +sudo apt remove -y $(dpkg --get-selections docker.io docker-compose docker-compose-v2 docker-doc podman-docker containerd runc | cut -f1) +sudo apt-get install -y uidmap +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh +# Don't install rootless because compose has certain things like setting ulimits which only rooted docker can do. +# dockerd-rootless-setuptool.sh install +# sudo loginctl enable-linger ubuntu diff --git a/erpnext-systemd/install-erpnext-systemd.sh b/erpnext-systemd/install-erpnext-systemd.sh new file mode 100644 index 0000000..befc7a5 --- /dev/null +++ b/erpnext-systemd/install-erpnext-systemd.sh @@ -0,0 +1,34 @@ +sudo apt-get update -y + +sudo apt-get install -y \ + valkey-server \ + pkg-config \ + mariadb-server \ + libmariadb-dev \ + libmariadb-dev-compat \ + build-essential \ + xvfb \ + libfontconfig \ + fontconfig \ + xfonts-75dpi + +sudo ln -s /usr/bin/valkey-server /usr/bin/redis-server + +wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-2/wkhtmltox_0.12.6.1-2.jammy_amd64.deb +sudo dpkg -i wkhtmltox_0.12.6.1-2.jammy_amd64.deb + +sudo apt --fix-broken install -y + + +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash +source ~/.bashrc +nvm install 24 +npm install -g yarn + + +curl -LsSf https://astral.sh/uv/0.10.9/install.sh | sh +source $HOME/.local/bin/env +uv python install 3.14 --default +uv tool install frappe-bench + +bench init frappe-bench --frappe-branch v16.10.10 diff --git a/headscale/headscale-install.sh b/headscale/headscale-install.sh new file mode 100644 index 0000000..9b2825d --- /dev/null +++ b/headscale/headscale-install.sh @@ -0,0 +1,324 @@ +HEADSCALE_VERSION="0.28.0" +HEADSCALE_ARCH="amd64" +DOMAIN_URL="https://vpn.excloud.in" + +wget --output-document=headscale.deb \ + "https://github.com/juanfont/headscale/releases/download/v${HEADSCALE_VERSION}/headscale_${HEADSCALE_VERSION}_linux_${HEADSCALE_ARCH}.deb" + +apt install ./headscale.deb + +systemctl enable --now headscale + +PREAUTH_KEY=$(headscale preauthkeys create --tags tag:headscale-agent) + +apt-get install caddy -y + +mkdir -p /var/lib/headplane +chown -R $(whoami):$(whoami) /var/lib/headplane +mkdir -p /etc/headplane +touch /etc/headplane/config.yaml + +wget https://go.dev/dl/go1.26.0.linux-amd64.tar.gz +tar -C /usr/local -xzf go1.26.0.linux-amd64.tar.gz +echo 'export PATH=$PATH:/usr/local/go/bin' >> /etc/profile +rm go1.26.0.linux-amd64.tar.gz + + +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash +\. "$HOME/.nvm/nvm.sh" +source ~/.bashrc +nvm install 24 + +git clone https://github.com/tale/headplane.git +cd headplane +COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack enable pnpm +COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack install +pnpm install +pnpm build + +cat > "/etc/caddy/Caddyfile" < "/etc/headplane/config.yaml" <" + +# Headscale specific settings to allow Headplane to talk +# to Headscale and access deep integration features +headscale: + # The URL to your Headscale instance + # (All API requests are routed through this URL) + # (THIS IS NOT the gRPC endpoint, but the HTTP endpoint) + # + # IMPORTANT: If you are using TLS this MUST be set to 'https://' + url: "http://127.0.0.1:8080" + + # If you use the TLS configuration in Headscale, and you are not using + # Let's Encrypt for your certificate, pass in the path to the certificate. + # (This has no effect if 'url' does not start with 'https://') + # tls_cert_path: "/var/lib/headplane/tls.crt" + + # Optional, public URL if its different from the 'headscale.url' + # This affects certain parts of the web UI which shows Headscale's URL + public_url: "${DOMAIN_URL}" + + # Path to the Headscale configuration file + # This is optional, but HIGHLY recommended for the best experience + # If this is read only, Headplane will show your configuration settings + # in the Web UI, but they cannot be changed. + config_path: "/etc/headscale/config.yaml" + + # Whether the Headscale configuration should be strictly validated + # when reading from 'config_path'. If true, Headplane will not interact + # with Headscale if there are any issues with the configuration file. + # + # This is recommended to be true for production deployments to, however it + # may not work if you are using a version of Headscale that has configuration + # options unknown to Headplane. + config_strict: true + + # If you are using 'dns.extra_records_path' in your Headscale + # configuration, you need to set this to the path for Headplane + # to be able to read the DNS records. + # + # Pass it in if using Docker and ensure that the file is both + # readable and writable to the Headplane process. + # When using this, Headplane will no longer need to automatically + # restart Headscale for DNS record changes. + # dns_records_path: "/var/lib/headscale/extra_records.json" + +# Integration configurations for Headplane to interact with Headscale +integration: + # The Headplane agent allows retrieving information about nodes + # This allows the UI to display version, OS, and connectivity data + # You will see the Headplane agent in your Tailnet as a node when + # it connects. + agent: + enabled: true + + # To connect to your Tailnet, you need to generate a pre-auth key + # This can be done via the web UI or through the 'headscale' CLI. + pre_authkey: "${PREAUTH_KEY}" + + # Optionally change the name of the agent in the Tailnet. + host_name: "headplane-agent" + + # Configure different caching settings. By default, the agent will store + # caches in the path below for a maximum of 1 minute. If you want data + # to update faster, reduce the TTL, but this will increase the frequency + # of requests to Headscale. + # cache_ttl: 60 + # cache_path: /var/lib/headplane/agent_cache.json + + # The work_dir represents where the agent will store its data to be able + # to automatically reauthenticate with your Tailnet. It needs to be + # writable by the user running the Headplane process. + # + # If using Docker, it is best to leave this as the default. + # work_dir: "/var/lib/headplane/agent" + + # Only one of these should be enabled at a time or you will get errors + # This does not include the agent integration (above), which can be enabled + # at the same time as any of these and is recommended for the best experience. + docker: + enabled: false + + # By default we check for the presence of a container label (see the docs) + # to determine the container to signal when changes are made to DNS settings. + container_label: "me.tale.headplane.target=headscale" + + # HOWEVER, you can fallback to a container name if you desire, but this is + # not recommended as its brittle and doesn't work with orchestrators that + # automatically assign container names. + # + # If 'container_name' is set, it will override any label checks. + # container_name: "headscale" + + # The path to the Docker socket (do not change this if you are unsure) + # Docker socket paths must start with unix:// or tcp:// and at the moment + # https connections are not supported. + socket: "unix:///var/run/docker.sock" + + # Please refer to docs/integration/Kubernetes.md for more information + # on how to configure the Kubernetes integration. There are requirements in + # order to allow Headscale to be controlled by Headplane in a cluster. + kubernetes: + enabled: false + # Validates the manifest for the Pod to ensure all of the criteria + # are set correctly. Turn this off if you are having issues with + # shareProcessNamespace not being validated correctly. + validate_manifest: true + # This should be the name of the Pod running Headscale and Headplane. + # If this isn't static you should be using the Kubernetes Downward API + # to set this value (refer to docs/Integrated-Mode.md for more info). + pod_name: "headscale" + + # Proc is the "Native" integration that only works when Headscale and + # Headplane are running outside of a container. There is no configuration, + # but you need to ensure that the Headplane process can terminate the + # Headscale process. + # + # (If they are both running under systemd as sudo, this will work). + proc: + enabled: false + +# OIDC Configuration for simpler authentication +# (This is optional, but recommended for the best experience) +# oidc: +# Set to false to define OIDC config without enabling it. +# Useful for Helm charts or generating docs from config files. +# enabled: true + +# The OIDC issuer URL +# issuer: "https://accounts.google.com" + +# If you are using OIDC, you need to generate an API key +# that can be used to authenticate other sessions when signing in. +# +# This can be done with 'headscale apikeys create --expiration 999d' +# headscale_api_key: "" + +# If your OIDC provider does not support discovery (does not have the URL at +# '/.well-known/openid-configuration'), you need to manually set endpoints. +# This also works to override endpoints if you so desire or if your OIDC +# discovery is missing certain endpoints (ie GitHub). +# For some typical providers, see https://headplane.net/features/sso. +# authorization_endpoint: "" +# token_endpoint: "" +# userinfo_endpoint: "" + +# The authentication method to use when communicating with the token endpoint. +# This is fully optional and Headplane will attempt to auto-detect the best +# method and fall back to 'client_secret_basic' if unsure. +# token_endpoint_auth_method: "client_secret_post" + +# The client ID for the OIDC client +# For the best experience please ensure this is *identical* to the client_id +# you are using for Headscale. because +# client_id: "your-client-id" + +# The client secret for the OIDC client +# You may also provide 'client_secret_path' instead to read a value from disk. +# See https://headplane.net/configuration/#sensitive-values +# client_secret: "" + +# Whether to use PKCE when authenticating users. This is recommended as it +# adds an extra layer of security to the authentication process. Enabling this +# means your OIDC provider must support PKCE and it must be enabled on the +# client. +# use_pkce: true + +# If you want to disable traditional login via Headscale API keys +# disable_api_key_login: false + +# By default profile pictures are pulled from the OIDC provider when +# we go to fetch the userinfo endpoint. Optionally, this can be set to +# "oidc" or "gravatar" as of 0.6.1. +# profile_picture_source: "gravatar" + +# The scopes to request when authenticating users. The default is below. +# scope: "openid email profile" + +# Extra query parameters can be passed to the authorization endpoint +# by setting them here. This is useful for providers that require any kind +# of custom hinting. +# extra_params: +# prompt: "select_account" # Example: force account selection on Google +EOF + +NODE_PATH=$(nvm which current) +cat > "/etc/systemd/system/headplane.service" <&2 + echo "domain-change.sh sub.example.com" >&2 + exit 1 +fi + +URL="https://${DOMAIN}" +COMPOSE_FILE="${APP_DIR}/signoz/deploy/docker/docker-compose.yaml" + +set_env() { + local key="$1" + local value="$2" + local service_path="$3" + local env_pair="${key}=${value}" + + if yq "${service_path}" "$COMPOSE_FILE" | grep -q "${key}="; then + yq -yi "(${service_path}[] | select(type == \"string\" and test(\"^${key}=\"))) = \"${env_pair}\"" "$COMPOSE_FILE" + echo "Replaced: ${env_pair}" + else + yq -yi "${service_path} += [\"${env_pair}\"]" "$COMPOSE_FILE" + echo "Added: ${env_pair}" + fi +} + +set_env "SIGNOZ_GLOBAL_EXTERNAL_URL" "${URL}" ".services.signoz.environment" +set_env "SIGNOZ_GLOBAL_INGESTION_URL" "${URL}" ".services.signoz.environment" + +cat > /etc/caddy/Caddyfile << EOF +${URL} { + reverse_proxy localhost:8080 +} + +${URL}:4317 { + reverse_proxy h2c://localhost:44317 +} + +${URL}:4318 { + reverse_proxy localhost:44318 +} +EOF + +echo "Caddyfile updated" + +docker compose -f $COMPOSE_FILE up -d --remove-orphans +systemctl reload caddy diff --git a/signoz/install-signoz.sh b/signoz/install-signoz.sh new file mode 100644 index 0000000..ea6928f --- /dev/null +++ b/signoz/install-signoz.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +APP_NAME="signoz" +APP_DIR="/var/excloud/apps" +SCRIPT_DIR="/var/excloud/scripts" +DOMAIN="${1}" +if [ -z "$DOMAIN" ]; then + echo "Error: URL argument is required. Example:" >&2 + echo "domain-change.sh sub.example.com" >&2 + exit 1 +fi +SIGNOZ_DIR="${APP_DIR}/signoz" +COMPOSE_FILE="${SIGNOZ_DIR}/deploy/docker/docker-compose.yaml" +OTEL_SERVICE_PATH='.services["otel-collector"].ports' +SIGNOZ_SERVICE_PATH=".services.signoz.ports" + +mkdir -p "${APP_DIR}" +mkdir -p "${SCRIPT_DIR}" + +apt-get install -y caddy yq + +rm -rf ${SIGNOZ_DIR} +git clone -b main https://github.com/SigNoz/signoz.git ${SIGNOZ_DIR} +cd ${SIGNOZ_DIR}/deploy/docker + +bash "${SCRIPT_DIR}/domain-signoz.sh" "${DOMAIN}" + +set_port() { + local port_pair="$1" + local service_path="$2" + local port_num="${port_pair##*:}" + + if yq "${service_path}[] | select(. == ${port_num} or (type == \"string\" and test(\"${port_num}:${port_num}\")))" "$COMPOSE_FILE" | grep -q .; then + yq -yi "(${service_path}[] | select(. == ${port_num} or (type == \"string\" and test(\"${port_num}:${port_num}\")))) = \"${port_pair}\"" "$COMPOSE_FILE" + echo "Replaced: ${port_pair}" + else + yq -yi "${service_path} += [\"${port_pair}\"]" "$COMPOSE_FILE" + echo "Added: ${port_pair}" + fi +} + +set_port "127.0.0.1:44317:4317" "$OTEL_SERVICE_PATH" +set_port "127.0.0.1:44318:4318" "$OTEL_SERVICE_PATH" +set_port "127.0.0.1:8080:8080" "$SIGNOZ_SERVICE_PATH" + +docker compose -f $COMPOSE_FILE up -d --remove-orphans