|
| 1 | +#!/bin/bash |
| 2 | +set -euo pipefail |
| 3 | + |
| 4 | +PROXY_URL="" |
| 5 | +if ! curl -sf --connect-timeout 5 --head {{.Endpoint}} > /dev/null 2>&1; then |
| 6 | + PROXY_URL="http://squid.corp.redhat.com:3128" |
| 7 | +fi |
| 8 | + |
| 9 | +# Download binary tarball — works on any Linux distro, no package manager needed |
| 10 | +TAR_URL="https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v{{.ColVersion}}/otelcol-contrib_{{.ColVersion}}_linux_{{.Arch}}.tar.gz" |
| 11 | +HTTPS_PROXY="$PROXY_URL" curl -fsSL -o /tmp/otelcol-contrib.tar.gz "$TAR_URL" |
| 12 | +tar -xzf /tmp/otelcol-contrib.tar.gz -C /tmp otelcol-contrib |
| 13 | +mv /tmp/otelcol-contrib /usr/local/bin/otelcol-contrib |
| 14 | +chmod 755 /usr/local/bin/otelcol-contrib |
| 15 | +chcon -t bin_t /usr/local/bin/otelcol-contrib 2>/dev/null || restorecon -v /usr/local/bin/otelcol-contrib 2>/dev/null || true |
| 16 | +rm -f /tmp/otelcol-contrib.tar.gz |
| 17 | + |
| 18 | +# Create dedicated system user (idempotent) |
| 19 | +useradd --system --no-create-home --shell /sbin/nologin otelcol-contrib 2>/dev/null || true |
| 20 | + |
| 21 | +# Create config and drop-in directories |
| 22 | +mkdir -p /etc/otelcol-contrib /etc/systemd/system/otelcol-contrib.service.d |
| 23 | + |
| 24 | +# Write systemd service unit |
| 25 | +cat > /etc/systemd/system/otelcol-contrib.service << 'SVCEOF' |
| 26 | +[Unit] |
| 27 | +Description=OpenTelemetry Collector Contrib |
| 28 | +After=network.target |
| 29 | +
|
| 30 | +[Service] |
| 31 | +User=otelcol-contrib |
| 32 | +Group=otelcol-contrib |
| 33 | +EnvironmentFile=/etc/otelcol-contrib/otelcol-contrib.conf |
| 34 | +EnvironmentFile=/etc/otelcol-contrib/auth_token |
| 35 | +ExecStart=/usr/local/bin/otelcol-contrib $OTELCOL_OPTIONS |
| 36 | +Restart=on-failure |
| 37 | +RestartSec=5s |
| 38 | +KillMode=process |
| 39 | +SyslogIdentifier=otelcol-contrib |
| 40 | +
|
| 41 | +[Install] |
| 42 | +WantedBy=multi-user.target |
| 43 | +SVCEOF |
| 44 | + |
| 45 | +# Drop-in: grant read access to all log files and expose hostname |
| 46 | +cat > /etc/systemd/system/otelcol-contrib.service.d/capabilities.conf << 'CAPEOF' |
| 47 | +[Service] |
| 48 | +AmbientCapabilities=CAP_DAC_READ_SEARCH |
| 49 | +Environment="HOSTNAME=%H" |
| 50 | +CAPEOF |
| 51 | + |
| 52 | +# Options file consumed by ExecStart |
| 53 | +printf 'OTELCOL_OPTIONS=--config /etc/otelcol-contrib/config.yaml\n' \ |
| 54 | + > /etc/otelcol-contrib/otelcol-contrib.conf |
| 55 | +chmod 640 /etc/otelcol-contrib/otelcol-contrib.conf |
| 56 | + |
| 57 | +# Auth token (mode 600 — readable only by otelcol-contrib user after chown) |
| 58 | +printf 'OTEL_AUTH_TOKEN={{.AuthToken}}\n' > /etc/otelcol-contrib/auth_token |
| 59 | +chmod 600 /etc/otelcol-contrib/auth_token |
| 60 | + |
| 61 | +# Collector configuration |
| 62 | +cat > /etc/otelcol-contrib/config.yaml << 'OTELEOF' |
| 63 | +receivers: |
| 64 | + filelog/syslog: |
| 65 | + include: |
| 66 | + - {{.SyslogPath}} |
| 67 | + start_at: end |
| 68 | + include_file_path: true |
| 69 | + include_file_name: true |
| 70 | + exclude_older_than: 24h |
| 71 | + operators: |
| 72 | + - type: move |
| 73 | + id: move_to_source_name |
| 74 | + from: attributes["log.file.path"] |
| 75 | + to: attributes["_sourceName"] |
| 76 | + - type: remove |
| 77 | + id: remove_file_name |
| 78 | + field: attributes["log.file.name"] |
| 79 | + - type: time_parser |
| 80 | + id: parse_timestamp |
| 81 | + layout: '%b %e %H:%M:%S' |
| 82 | + parse_from: body |
| 83 | + on_error: send |
| 84 | + attributes: |
| 85 | + index: "{{.Index}}" |
| 86 | + _sourceCategory: syslog |
| 87 | + _sourceHost: ${env:HOSTNAME} |
| 88 | + filelog/secure: |
| 89 | + include: |
| 90 | + - {{.SecurePath}} |
| 91 | + start_at: end |
| 92 | + include_file_path: true |
| 93 | + include_file_name: true |
| 94 | + exclude_older_than: 24h |
| 95 | + operators: |
| 96 | + - type: move |
| 97 | + id: move_to_source_name |
| 98 | + from: attributes["log.file.path"] |
| 99 | + to: attributes["_sourceName"] |
| 100 | + - type: remove |
| 101 | + id: remove_file_name |
| 102 | + field: attributes["log.file.name"] |
| 103 | + - type: time_parser |
| 104 | + id: parse_timestamp |
| 105 | + layout: '%b %e %H:%M:%S' |
| 106 | + parse_from: body |
| 107 | + on_error: send |
| 108 | + attributes: |
| 109 | + index: "{{.Index}}" |
| 110 | + _sourceCategory: secure |
| 111 | + _sourceHost: ${env:HOSTNAME} |
| 112 | + filelog/audit: |
| 113 | + include: |
| 114 | + - /var/log/audit/audit.log |
| 115 | + start_at: end |
| 116 | + include_file_path: true |
| 117 | + include_file_name: true |
| 118 | + exclude_older_than: 24h |
| 119 | + operators: |
| 120 | + - type: move |
| 121 | + id: move_to_source_name |
| 122 | + from: attributes["log.file.path"] |
| 123 | + to: attributes["_sourceName"] |
| 124 | + - type: remove |
| 125 | + id: remove_file_name |
| 126 | + field: attributes["log.file.name"] |
| 127 | + attributes: |
| 128 | + index: "{{.Index}}" |
| 129 | + _sourceCategory: audit |
| 130 | + _sourceHost: ${env:HOSTNAME} |
| 131 | +{{- if .MonitorGitLabRunner}} |
| 132 | + filelog/gitlab-runner: |
| 133 | + include: |
| 134 | + - /var/log/gitlab-runner/runner.log |
| 135 | + start_at: end |
| 136 | + include_file_path: true |
| 137 | + include_file_name: true |
| 138 | + operators: |
| 139 | + - type: move |
| 140 | + id: move_to_source_name |
| 141 | + from: attributes["log.file.path"] |
| 142 | + to: attributes["_sourceName"] |
| 143 | + - type: remove |
| 144 | + id: remove_file_name |
| 145 | + field: attributes["log.file.name"] |
| 146 | + attributes: |
| 147 | + index: "{{.Index}}" |
| 148 | + _sourceCategory: gitlab-runner |
| 149 | + _sourceHost: ${env:HOSTNAME} |
| 150 | +{{- end}} |
| 151 | +processors: |
| 152 | + filter/drop_null_bytes: |
| 153 | + logs: |
| 154 | + log_record: |
| 155 | + - 'IsMatch(body, "^\x00+$")' |
| 156 | + batch: |
| 157 | + timeout: "1s" |
| 158 | + send_batch_size: 1024 |
| 159 | + resource: |
| 160 | + attributes: |
| 161 | + - key: appcode |
| 162 | + value: "{{.AppCode}}" |
| 163 | + action: upsert |
| 164 | + - key: com.redhat.otel.auth_token |
| 165 | + value: "${env:OTEL_AUTH_TOKEN}" |
| 166 | + action: upsert |
| 167 | + - key: arch |
| 168 | + value: "{{.Arch}}" |
| 169 | + action: upsert |
| 170 | +{{- range $k, $v := .ExtraAttrs}} |
| 171 | + - key: {{$k}} |
| 172 | + value: "{{$v}}" |
| 173 | + action: upsert |
| 174 | +{{- end}} |
| 175 | +exporters: |
| 176 | + otlphttp: |
| 177 | + endpoint: "{{.Endpoint}}" |
| 178 | + tls: |
| 179 | + insecure_skip_verify: true |
| 180 | +service: |
| 181 | + telemetry: |
| 182 | + logs: |
| 183 | + level: "fatal" |
| 184 | + metrics: |
| 185 | + level: "basic" |
| 186 | + pipelines: |
| 187 | + logs: |
| 188 | + receivers: [filelog/syslog, filelog/secure, filelog/audit{{if .MonitorGitLabRunner}}, filelog/gitlab-runner{{end}}] |
| 189 | + processors: [filter/drop_null_bytes, resource, batch] |
| 190 | + exporters: [otlphttp] |
| 191 | +OTELEOF |
| 192 | + |
| 193 | +# Transfer ownership to the service user |
| 194 | +chown -R otelcol-contrib:otelcol-contrib /etc/otelcol-contrib |
| 195 | + |
| 196 | +# Set up proxy drop-in if direct access to the endpoint was unavailable |
| 197 | +if [ -n "$PROXY_URL" ]; then |
| 198 | + printf '[Service]\nEnvironment="HTTPS_PROXY=%s/"\nEnvironment="NO_PROXY=10.*,192.168.*,localhost,127.0.0.1"\n' "$PROXY_URL" \ |
| 199 | + > /etc/systemd/system/otelcol-contrib.service.d/proxy.conf |
| 200 | +fi |
| 201 | + |
| 202 | +systemctl daemon-reload |
| 203 | +systemctl enable --now otelcol-contrib |
0 commit comments